简体   繁体   English

使用计时器在JLabel中刷新图像

[英]Refresh Image in JLabel with Timer

I´m currently working on a little programm witch displays pictures from a website in a little Swing GUI. 我目前正在研究一个小型程序,在一个Swing GUI中显示网站上的图片。 The Problem is, that every time the picture changes a new frame pops up instead of refreshing the JLable. 问题是,每次图片更改时,都会弹出一个新帧,而不是刷新JLable。

I have no idea how to realize this after trying a few attempts with different methods. 在尝试使用不同方法的几次尝试之后,我不知道如何实现这一点。

It would be nice if you could give me a little hint. 如果您能给我一点提示,那就太好了。

import java.awt.BorderLayout;
import java.awt.Image;
import java.io.*;
import java.net.MalformedURLException;
import java.net.URL;

import javax.imageio.ImageIO;
import javax.swing.*;


public class PageReader extends JFrame {

    JLabel picture;
    static String[] viewable;
    int counter;
    static String urlString;
    Image image;
    URL url;

    public PageReader(int pos) throws IOException
    {
        urlString = "http:"+viewable[pos];

        url = new URL(urlString);
        image = ImageIO.read(url);

        ImageIcon icon = new ImageIcon(image); 

        picture = new JLabel();
        picture.setIcon(icon);


        int breite = icon.getImage().getWidth(this);
        int hoehe = icon.getImage().getHeight(this);


        do
        {
            if(hoehe>400)
            {
                breite *= 0.75;
                hoehe *= 0.75;
                icon.setImage(icon.getImage().getScaledInstance(breite, hoehe, image.SCALE_DEFAULT));
            }

            if(hoehe<400)
            {
                hoehe *= 1.2;
                breite *=1.2;
                icon.setImage(icon.getImage().getScaledInstance(breite, hoehe, image.SCALE_DEFAULT));
            }
        }while(hoehe>400&&hoehe<300);


        icon.setImage(icon.getImage().getScaledInstance(breite, hoehe, image.SCALE_DEFAULT));


        JPanel anzeige = new JPanel();
        anzeige.add(picture, BorderLayout.CENTER);

        setContentPane(anzeige);


        pack();
        setResizable(false);
        setVisible(true);
    }



    public static void main(String[] args) throws IOException, InterruptedException {
        // TODO Auto-generated method stub

        String meineURL = "http://www.pr0gramm.com/static/";

         URL url = new URL(meineURL);

         InputStreamReader isr = new InputStreamReader(url.openConnection().getInputStream());
         BufferedReader br = new BufferedReader(isr);

         // Kompletten Seiteninhalt auslesen
         String line ="";
         String quelltext ="";

         while((line = br.readLine()) != null)
         {
         quelltext += line + "\r\n";
         }

         // Reader Schließen
         br.close();
         isr.close();

         String test = quelltext.substring(1708);
         String[] parts = test.split("<a href=");


         for(int i=1; i<parts.length; i++)
         {
             parts[i]=parts[i].substring(1,15);
         }

         viewable = new String[parts.length];

         for(int i = 1; i<(parts.length-1); i++)
         {
             String sitePath = "http://pr0gramm.com"+parts[i];

             meineURL = sitePath;

             url = new URL(meineURL);

             isr = new InputStreamReader(url.openConnection().getInputStream());
             br = new BufferedReader(isr);

             // Kompletten Seiteninhalt auslesen
             line ="";
             quelltext ="";

             while((line = br.readLine()) != null)
             {
             quelltext += line + "\r\n";
             }

             CharSequence picPath = quelltext.subSequence(quelltext.indexOf("//img.pr0gramm.com/"), quelltext.indexOf("//img.pr0gramm.com/")+50);

             viewable[i] = picPath.toString();

             // Seiteninhalt ausgeben
             //System.out.println(quelltext);
             System.out.println(viewable[i]);
         }

         System.out.println("\nLink-Counter: "+viewable.length);
         //System.out.println("//img.pr0gramm.com/2015/06/25/87fd872bde0ab593.jpg");

         new PageReader(4);
         //System.out.println("\n \n \n Sub \n \n"+test);
         for(int i = 1; i<viewable.length; i++)
         {
             if(!(viewable[i].contains(".web")))
             {
                url = new URL("http:"+viewable[i]);

                new PageReader(i);

                System.out.println("test"+i);
                urlString = "http:"+viewable[i];
                Thread.sleep(5000);
             }
         }


    }

}

This is my current code. 这是我当前的代码。

Start by taking a look at Concurrency in Swing and Worker Threads and SwingWorker 首先了解一下SwingWorker线程中的并发性 以及SwingWorker

You might also like to take a look at jsoup as using String#substring etc to parse html is a really bad idea 您可能还想看看jsoup,因为使用String#substring等解析html是一个非常糟糕的主意

Swing is single threaded, meaining your can't block the Event Dispatching Thread with blocking or long running processes (like Thread.sleep ), but it is also not thread safe, meaning you shouldn't modify it from outside of EDT either. Swing是单线程的,这意味着您无法使用阻塞或长时间运行的进程(例如Thread.sleep )来阻塞事件调度线程,但是它也不是线程安全的,这意味着您也不应该在EDT外部进行修改。

To this end, SwingWorker presents a reasonable solution, as it can process the html and image downloading outside of the EDT, but provides a number of ways you can resync updates to the EDT. 为此, SwingWorker提供了一种合理的解决方案,因为它可以处理EDT外部的html和图像下载,但是提供了许多将更新重新同步到EDT的方法。

To start with, you need to be updating the JLabel 's icon property and not creating new instances of PageReader , which is one of the (many) reasons we generally discourage people from extending from JFrame . 首先,您需要更新JLabelicon属性,而不要创建PageReader新实例,这是我们通常不鼓励人们从JFrame扩展的(许多)原​​因之一。

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.List;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingWorker;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private JLabel label;

        public TestPane() {
            setLayout(new BorderLayout());
            label = new JLabel("Loading...");
            label.setHorizontalAlignment(JLabel.CENTER);
            label.setVerticalAlignment(JLabel.CENTER);
            add(label);
            ImageWorker worker = new ImageWorker(label);
            worker.execute();
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(400, 400);
        }

        public class ImageWorker extends SwingWorker<Object, Image> {

            private JLabel output;

            public ImageWorker(JLabel output) {
                this.output = output;
            }

            @Override
            protected void process(List<Image> chunks) {
                output.setText(null);
                output.setIcon(new ImageIcon(chunks.get(chunks.size() - 1)));
            }

            @Override
            protected Object doInBackground() throws Exception {
                String meineURL = "http://www.pr0gramm.com/static/";

                URL url = new URL(meineURL);

                String quelltext = "";
                try (InputStreamReader isr = new InputStreamReader(url.openConnection().getInputStream()); BufferedReader br = new BufferedReader(isr)) {

                    // Kompletten Seiteninhalt auslesen
                    String line = "";

                    while ((line = br.readLine()) != null) {
                        quelltext += line + "\r\n";
                    }

                }

                String test = quelltext.substring(1708);
                String[] parts = test.split("<a href=");

                for (int i = 1; i < parts.length; i++) {
                    parts[i] = parts[i].substring(1, 15);
                }

                String[] viewable = new String[parts.length];

                for (int i = 1; i < (parts.length - 1); i++) {
                    String sitePath = "http://pr0gramm.com" + parts[i];

                    meineURL = sitePath;

                    url = new URL(meineURL);

                    try (InputStreamReader isr = new InputStreamReader(url.openConnection().getInputStream()); BufferedReader br = new BufferedReader(isr)) {

                        // Kompletten Seiteninhalt auslesen
                        String line = "";
                        quelltext = "";

                        while ((line = br.readLine()) != null) {
                            quelltext += line + "\r\n";
                        }

                        CharSequence picPath = quelltext.subSequence(quelltext.indexOf("//img.pr0gramm.com/"), quelltext.indexOf("//img.pr0gramm.com/") + 50);

                        viewable[i] = picPath.toString();

                    }
                }

                System.out.println("\nLink-Counter: " + viewable.length);

                for (int i = 1; i < viewable.length; i++) {
                    if (!(viewable[i].contains(".web"))) {
                        url = new URL("http:" + viewable[i]);

                        System.out.println("Reading " + url);
                        BufferedImage original = ImageIO.read(url);
                        Image image = original;

                        if (original.getWidth() > original.getHeight()) {
                            image = original.getScaledInstance(400, -1, Image.SCALE_SMOOTH);
                        } else {
                            image = original.getScaledInstance(-1, 400, Image.SCALE_SMOOTH);
                        }

                        publish(image);

                        System.out.println("test" + i);
                        Thread.sleep(5000);
                    }
                }

                return null;

            }

        }

    }

}

Should also have a look at The try-with-resources Statement for better ideas on how to manage your resources 还应该查看“尝试使用资源”语句,以获取有关如何管理资源的更好的想法

I didn't want to introduce more code into the example, but you should avoid using getScaledInstance if you can, see The Perils of Image.getScaledInstance() for more details. 我不想在示例中引入更多代码,但是如果可以的话,应该避免使用getScaledInstance ,有关更多详细信息,请参见Image.getScaledInstance()的危险

You can take a look at Java: maintaining aspect ratio of JPanel background image and Quality of Image after resize very low -- Java for alternatives 您可以看一下Java: 调整很小的尺寸后,可以保持JPanel背景图像的长宽比图像 质量-替代Java

I can't understand the variable naming conventions due to the different language.But, from what I can understand,I think u should not call new PageReader() on every update. 由于语言不同,我无法理解变量命名约定。但是,据我了解,我认为您不应在每次更新时都调用new PageReader()

Instead you should call something like update(int pos) 相反,您应该调用类似update(int pos)

public void update(int pos)
{
    //The Code that went into your constructor
}

This will ensure that the same JFrame is reused instead of a new one being created. 这将确保重用相同的JFrame ,而不是创建新的JFrame

Also I don't think u should initialize a new JLabel or JPanel everytime,instead u should add the JLabel to the JPanel in your constructor and in the update function, call picture.setIcon(icon); 我也不认为您应该每次都初始化一个新的JLabelJPanel ,相反,您应该在构造函数和update函数中调用JLabelJLabel添加到JPanel中,调用picture.setIcon(icon); without creating a new JLabel . 而不创建新的JLabel

Your constructor should look something like this : 您的构造函数应如下所示:

public PageReader()
{
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    picture=new JLabel();
    JPanel anzeige = new JPanel();
    anzeige.add(picture, BorderLayout.CENTER);

    setContentPane(anzeige);


    pack();
    setResizable(false);
    setVisible(true);
}

The remaining part of code in your constructor should go to update 构造函数中的代码其余部分应update

EDIT : 编辑:

public void update(int pos) throws IOException
{
    urlString = "http:"+viewable[pos];

    url = new URL(urlString);
    image = ImageIO.read(url);

    ImageIcon icon = new ImageIcon(image); 

    picture.setIcon(icon);


    int breite = icon.getImage().getWidth(this);
    int hoehe = icon.getImage().getHeight(this);


    do
    {
        if(hoehe>400)
        {
            breite *= 0.75;
            hoehe *= 0.75;
            icon.setImage(icon.getImage().getScaledInstance(breite, hoehe, image.SCALE_DEFAULT));
        }

        if(hoehe<400)
        {
            hoehe *= 1.2;
            breite *=1.2;
            icon.setImage(icon.getImage().getScaledInstance(breite, hoehe, image.SCALE_DEFAULT));
        }
    }while(hoehe>400&&hoehe<300);


    icon.setImage(icon.getImage().getScaledInstance(breite, hoehe, image.SCALE_DEFAULT));

}

Now in the main class, U should declare something like 现在在主类中,U应该声明类似

PageReader pr=new PageReader

Wherever U are using new PageReader(4) , u should use pr.update(4) 无论您在哪里使用new PageReader(4) ,都应该使用pr.update(4)

@MegaCleptomaniac, I am no expert on image stuff,so I think you should listen to what @MadProgrammer says about not using getScaledInstance @MegaCleptomaniac,我不是图像方面的专家,所以我认为您应该听@MadProgrammer所说的关于不使用getScaledInstance

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM