Search code examples
javaswingconcurrencytimerevent-dispatch-thread

How to show and hide images in swing using timer?


Is there any way I can just show and hide some images according to the input.

I am using character array of "T" and "F", if it is "T" then it will show image, if not then it will disable.

All I did is used JLabel and set ImageIcon to it. It shows and hides the image, but using timer, it just refreshes whole thing. Like if there is image for a "T" value, and if next loop of timer has "T" value for arr[2] as previous, then it should just stay there instead of refreshing the whole thing i.e. it blinks.

My code is as follows:

    Timer timer = new Timer();
    TimerTask task = new TimerTask() {
        @Override
        public void run() {
            // TODO Auto-generated method stub
            frame.getContentPane().removeAll();
            call();
        }
    };
    timer.schedule(task, 0, 2000);
}

static void call() {

    String S = "";


    for (int i = 0; i < bool.length; i++) {
        bool[i] = r.nextBoolean();
        if (bool[i]) {
            S = S + "T";
        } else {
            S = S + "F";
        }
    }
    System.out.print(S + "\n");

    char[] chars = S.toCharArray();
    for (int i = 0; i < chars.length; i++) {
        if ('T' == chars[i]) {
            label[i] = new JLabel(img);
            frame.getContentPane().add(label[i]);
        } else {
            label[i] = new JLabel(img1);
            frame.getContentPane().add(label[i]);
        }
        frame.setVisible(true);
    }
}

All I want is UI which shows and hides the image in certain time intervals, like in Android, I can use setVisibility for TextView.


Solution

  • TimerTask is not appropriate for this task, as it does not respect the single thread rules of Swing (see Concurrency in Swing for more details).

    Instead, you should be using a javax.swing.Timer, which will ensure that the "tick" event is executed within the Event Dispatching Thread.

    import java.awt.BorderLayout;
    import java.awt.Dimension;
    import java.awt.EventQueue;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.GridBagLayout;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JPanel;
    import javax.swing.Timer;
    import javax.swing.UIManager;
    import javax.swing.UnsupportedLookAndFeelException;
    
    public class Blinky01 {
    
        public static void main(String[] args) {
            new Blinky01();
        }
    
        public Blinky01() {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    try {
                        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    }
    
                    JFrame frame = new JFrame("Testing");
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.setLayout(new BorderLayout());
                    frame.add(new TestPane());
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                }
            });
        }
    
        public class TestPane extends JPanel {
    
            private JLabel label;
    
            public TestPane() {
                setLayout(new GridBagLayout());
                label = new JLabel("0");
                add(label);
                Timer timer = new Timer(1000, new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        boolean value = (((int) Math.round(Math.random() * 1))) == 0 ? false : true;
                        System.out.println(value);
                        label.setText(value ? "1" : "0");
                    }
                });
                timer.setRepeats(true);
                timer.setCoalesce(true);
                timer.setInitialDelay(0);
                timer.start();
            }
    
            @Override
            public Dimension getPreferredSize() {
                return new Dimension(200, 200);
            }
        }
    }