Search code examples
javaswingtimerjlabelimageicon

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. The Problem is, that every time the picture changes a new frame pops up instead of refreshing the 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.


Solution

  • Start by taking a look at Concurrency in Swing and Worker Threads and SwingWorker

    You might also like to take a look at jsoup as using String#substring etc to parse html is a really bad idea

    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.

    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.

    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.

    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.

    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