Update JLabel every X seconds from ArrayList<List> - Java

I have a simple Java program that reads in a text file, splits it by " " (spaces), displays the first word, waits 2 seconds, displays the next... etc... I would like to do this in Spring or some other GUI.

Any suggestions on how I can easily update the words with spring? Iterate through my list and somehow use setText();

I am not having any luck. I am using this method to print my words out in the consol and added the JFrame to it... Works great in the consol, but puts out endless jframe. I found most of it online.

    private void printWords() {
        for (int i = 0; i < words.size(); i++) {
            //How many words?
            //System.out.print(words.size());
            //print each word on a new line...
            Word w = words.get(i);
            System.out.println(w.name);

            //pause between each word.
            try{
                Thread.sleep(500);
            } 
            catch(InterruptedException e){
                e.printStackTrace();
            }
         JFrame frame = new JFrame("Run Text File"); 
         frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
         JLabel textLabel = new JLabel(w.name,SwingConstants.CENTER);
         textLabel.setPreferredSize(new Dimension(300, 100)); 
         frame.getContentPane().add(textLabel, BorderLayout.CENTER);
        //Display the window. frame.setLocationRelativeTo(null); 
         frame.pack(); 
         frame.setVisible(true);
        }
    }

I have a window that get's created with JFrame and JLable, however, I would like to have the static text be dynamic instead of loading a new spring window. I would like it to flash a word, disappear, flash a word disappear.

Any suggestions on how to update the JLabel? Something with repaint()? I am drawing a blank.

Thanks!

UPDATE: With the help from the kind folks below, I have gotten it to print correctly to the console. Here is my Print Method:

private void printWords() {
            final Timer timer = new Timer(500, null);
            ActionListener listener = new ActionListener() {
                private Iterator<Word> w = words.iterator();
                @Override 
                public void actionPerformed(ActionEvent e) {
                    if (w.hasNext()) {
                        _textField.setText(w.next().getName());
                        //Prints to Console just Fine...
                        //System.out.println(w.next().getName());
                    }
                    else {
                        timer.stop();
                    }
                }
            };
            timer.addActionListener(listener);
            timer.start();

    }

However, it isn't updating the lable? My contructor looks like:

public TimeThis() {

    _textField = new JTextField(5);
    _textField.setEditable(false);
    _textField.setFont(new Font("sansserif", Font.PLAIN, 30));

    JPanel content = new JPanel();
    content.setLayout(new FlowLayout());
    content.add(_textField); 

    this.setContentPane(content);
    this.setTitle("Swing Timer");
    this.pack();
    this.setLocationRelativeTo(null);
    this.setResizable(false);
    //_textField.setText("loading...");

}

Getting there... I'll post the fix once I, or whomever assists me, get's it working. Thanks again!


Solution 1:

First, build and display your GUI. Once the GUI is displayed, use a javax.swing.Timer to update the GUI every 500 millis:

final Timer timer = new Timer(500, null);
ActionListener listener = new ActionListsner() {
    private Iterator<Word> it = words.iterator();
    @Override 
    public void actionPerformed(ActionEvent e) {
        if (it.hasNext()) {
            label.setText(it.next().getName());
        }
        else {
            timer.stop();
        }
    }
};
timer.addActionListener(listener);
timer.start();

Solution 2:

Never use Thread.sleep(int) inside Swing Code, because it blocks the EDT; more here,

The result of using Thread.sleep(int) is this:

enter image description here

When Thread.sleep(int) ends

enter image description here

Example code:

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.image.BufferedImage;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Random;
import javax.swing.*;
//http://stackoverflow.com/questions/7943584/update-jlabel-every-x-seconds-from-arraylistlist-java
public class ButtonsIcon extends JFrame implements Runnable {

    private static final long serialVersionUID = 1L;
    private Queue<Icon> iconQueue = new LinkedList<Icon>();
    private JLabel label = new JLabel();
    private Random random = new Random();
    private JPanel buttonPanel = new JPanel();
    private JPanel labelPanel = new JPanel();
    private Timer backTtimer;
    private Timer labelTimer;
    private JLabel one = new JLabel("one");
    private JLabel two = new JLabel("two");
    private JLabel three = new JLabel("three");
    private final String[] petStrings = {"Bird", "Cat", "Dog",
        "Rabbit", "Pig", "Fish", "Horse", "Cow", "Bee", "Skunk"};
    private boolean runProcess = true;
    private int index = 1;
    private int index1 = 1;

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                ButtonsIcon t = new ButtonsIcon();
            }
        });
    }

    public ButtonsIcon() {
        iconQueue.add(UIManager.getIcon("OptionPane.errorIcon"));
        iconQueue.add(UIManager.getIcon("OptionPane.informationIcon"));
        iconQueue.add(UIManager.getIcon("OptionPane.warningIcon"));
        iconQueue.add(UIManager.getIcon("OptionPane.questionIcon"));

        one.setFont(new Font("Dialog", Font.BOLD, 24));
        one.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        two.setFont(new Font("Dialog", Font.BOLD, 24));
        two.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        three.setFont(new Font("Dialog", Font.BOLD, 10));
        three.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        labelPanel.setLayout(new GridLayout(0, 3, 4, 4));

        labelPanel.add(one);
        labelPanel.add(two);
        labelPanel.add(three);
        //labelPanel.setBorder(new LineBorder(Color.black, 1));
        labelPanel.setOpaque(false);

        JButton button0 = createButton();
        JButton button1 = createButton();
        JButton button2 = createButton();
        JButton button3 = createButton();

        buttonPanel.setLayout(new GridLayout(0, 4, 4, 4));
        buttonPanel.add(button0);
        buttonPanel.add(button1);
        buttonPanel.add(button2);
        buttonPanel.add(button3);
        //buttonPanel.setBorder(new LineBorder(Color.black, 1));
        buttonPanel.setOpaque(false);

        label.setLayout(new BorderLayout());
        label.add(labelPanel, BorderLayout.NORTH);
        label.add(buttonPanel, BorderLayout.SOUTH);
        Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
        label.setPreferredSize(new Dimension(d.width / 3, d.height / 3));

        add(label, BorderLayout.CENTER);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        pack();
        setVisible(true);
        startBackground();
        startLabel2();
        new Thread(this).start();
        printWords(); // generating freeze Swing GUI durring EDT
    }

    private JButton createButton() {
        JButton button = new JButton();
        button.setBorderPainted(false);
        button.setBorder(null);
        button.setFocusable(false);
        button.setMargin(new Insets(0, 0, 0, 0));
        button.setContentAreaFilled(false);
        button.setIcon(nextIcon());
        button.setRolloverIcon(nextIcon());
        button.setPressedIcon(nextIcon());
        button.setDisabledIcon(nextIcon());
        nextIcon();
        return button;
    }

    private Icon nextIcon() {
        Icon icon = iconQueue.peek();
        iconQueue.add(iconQueue.remove());
        return icon;
    }

    // Update background at 4/3 Hz
    private void startBackground() {
        backTtimer = new javax.swing.Timer(750, updateBackground());
        backTtimer.start();
        backTtimer.setRepeats(true);
    }

    private Action updateBackground() {
        return new AbstractAction("Background action") {

            private static final long serialVersionUID = 1L;

            @Override
            public void actionPerformed(ActionEvent e) {
                label.setIcon(new ImageIcon(getImage()));
            }
        };
    }

    // Update Label two at 2 Hz
    private void startLabel2() {
        labelTimer = new javax.swing.Timer(500, updateLabel2());
        labelTimer.start();
        labelTimer.setRepeats(true);
    }

    private Action updateLabel2() {
        return new AbstractAction("Label action") {

            private static final long serialVersionUID = 1L;

            @Override
            public void actionPerformed(ActionEvent e) {
                two.setText(petStrings[index]);
                index = (index + 1) % petStrings.length;
            }
        };
    }

    // Update lable one at 3 Hz
    @Override
    public void run() {
        while (runProcess) {
            SwingUtilities.invokeLater(new Runnable() {

                @Override
                public void run() {
                    one.setText(petStrings[index1]);
                    index1 = (index1 + 1) % petStrings.length;
                }
            });
            try {
                Thread.sleep(300);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    // Note: blocks EDT
    private void printWords() {
        for (int i = 0; i < petStrings.length; i++) {
            String word = petStrings[i].toString();
            System.out.println(word);
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            three.setText(word);
        }
        three.setText("<html> Concurency Issues in Swing<br>"
                + " never to use Thread.sleep(int) <br>"
                + " durring EDT, simple to freeze GUI </html>");
    }

    public BufferedImage getImage() {
        int w = label.getWidth();
        int h = label.getHeight();
        GradientPaint gp = new GradientPaint(0f, 0f, new Color(
                127 + random.nextInt(128),
                127 + random.nextInt(128),
                127 + random.nextInt(128)),
                w, w,
                new Color(random.nextInt(128), random.nextInt(128), random.nextInt(128)));
        BufferedImage bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
        Graphics2D g2d = bi.createGraphics();
        g2d.setPaint(gp);
        g2d.fillRect(0, 0, w, h);
        g2d.setColor(Color.BLACK);
        return bi;
    }
}

Solution 3:

    import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;

import javax.swing.*;


class TimeThis extends JFrame {

    private static final long serialVersionUID = 1L;
    private ArrayList<Word> words;
    private JTextField _textField;  // set by timer listener

    public TimeThis() throws IOException {

        _textField = new JTextField(5);
        _textField.setEditable(false);
        _textField.setFont(new Font("sansserif", Font.PLAIN, 30));

        JPanel content = new JPanel();
        content.setLayout(new FlowLayout());
        content.add(_textField); 

        this.setContentPane(content);
        this.setTitle("Swing Timer");
        this.pack();
        this.setLocationRelativeTo(null);
        this.setResizable(false);
        _textField.setText("loading...");

        readFile(); // read file
        printWords(); // print results
    }

    public void readFile(){

        try {
            BufferedReader in = new BufferedReader(new FileReader("adameve.txt"));
            words = new ArrayList<Word>();
            int lineNum = 1; // we read first line in start

            // delimeters of line in this example only "space"
            char [] parse = {' '};
            String delims = new String(parse);

            String line = in.readLine();
            String [] lineWords = line.split(delims);

            // split the words and create word object
            //System.out.println(lineWords.length);

            for (int i = 0; i < lineWords.length; i++) {
                Word w = new Word(lineWords[i]); 
                words.add(w);                                      
            }
            lineNum++;    // pass the next line

            line = in.readLine();

            in.close();

        } catch (IOException e) {
        }
    }
    private void printWords() {
            final Timer timer = new Timer(100, null);

            ActionListener listener = new ActionListener() {
                private Iterator<Word> w = words.iterator();
                @Override 
                public void actionPerformed(ActionEvent e) {
                    if (w.hasNext()) {
                        _textField.setText(w.next().getName());
                        //Prints to Console just Fine...
                        //System.out.println(w.next().getName());   
                    }
                    else {
                        timer.stop();
                    }
                }
            };
            timer.addActionListener(listener);
            timer.start();

    }
    class Word{
        private String name;

        public Word(String name) {
            this.name = name;
        }
        public String getName() {
            return name;
        }    
    }   

    public static void main(String[] args) throws IOException {
        JFrame ani = new TimeThis();
        ani.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        ani.setVisible(true); 

    }
}

I got it working with this code... Hope it can help someone else expand on their Java knowledge. Also, if anyone has any recommendations on cleaning this up. Please do so!