Refresh Image in JLabel with Timer

570 views Asked by At

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.

2

There are 2 answers

3
MadProgrammer On BEST ANSWER

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

2
Yash Srivastav On

I can't understand the variable naming conventions due to the different language.But, from what I can understand,I think u should not callnew PageReader() on every update.

Instead you should call something like 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.

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); without creating a new 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

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

PageReader pr=new PageReader

Wherever U are using new PageReader(4), u should use 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