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

4

4

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!

Clarisaclarise answered 30/10, 2011 at 6:11 Comment(6)
Off-topic question: Your gravatar, what is that called? I see it everywhere but can't find a name for it.Isabel
Hi Martinjn, it is called a QRCODE: en.wikipedia.org/wiki/QR_codeClarisaclarise
What does "spring window" mean? To me it seems like an HTML pop-up.Erzurum
@buildakicker : you're confusing Spring (an IOC framework and much more) and Swing (the standard desktop GUI framework of Java)Sfax
am I dreaming, hmmm maybe yesterday was drinking day, no, not never use Thread.sleep(int) inside Swing Code, because block EDT, see my post here @JB Nizet ++++++++++++++++++++++++++++++++++++++++++++++++Monocot
@JB Nizet, yes I did get those confused. Sorry for the confusion there. I am new to Java and there are SO MANY "THINGS!" out there for it. Killer deal though. Love it... suck at it, but loving it.Clarisaclarise
S
6

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();
Sfax answered 30/10, 2011 at 9:48 Comment(4)
I am going crazy over this. I just don't get how to get the timer to update the text. I can do it no problem with a String Array, but for some reason, when I try to read in a file, all breaks...Clarisaclarise
The GUI code should not read the file directly. Read the whole file in memory, store its content in a list in memory, and use the above code (unless of course the file is really too large to fit in memory).Sfax
It's not super big. About 2000 words max. So it should be like this: public class TText{ Declare VARS; SHOW GUI{} GET TEXT IN{} PRINT TEXT OUT{} ACTIONLISTENER with TIMER updates GUI{} } Does that look right?Clarisaclarise
Ok, finally got it working sort of... It prints to the console now. However, doesn't update label.setText() yet... Closer!Clarisaclarise
M
6

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.*;
//https://mcmap.net/q/456467/-update-jlabel-every-x-seconds-from-arraylist-lt-list-gt-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;
    }
}
Monocot answered 30/10, 2011 at 10:31 Comment(6)
@Andrew Thompson I share your great idea, but void convertToFromBytes work strange. isn't there another way how to converting Graphics2D to the plain Image FileMonocot
+1 I took the liberty of refactoring your instructive example.Fossil
@Fossil thanks!, since I created this quickly codes example upto 10mins, your coding skills/dimensions still missed somwhere in my newbee mind, really I must start to learn How to wrote code (I cann't refuse wrong programing habits from RPG/Cobol)Monocot
@Fossil I tried your changes on full screen size(2x FullHd monitor), these things to protect the world against stupidity, again thank youMonocot
@Monocot : Many new things for me to learn in this code, You really are too good in Swing :-)Littlejohn
@Gagandeep Bali then you must to click to the edited Nov 4 '11 at 8:18, then you'll see who is here good in Swing :-)Monocot
C
1
    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!

Clarisaclarise answered 15/11, 2011 at 0:17 Comment(1)
+1, just a small suggestion, the contents of your main method, must be wrapped inside SwingUtilities.invokeLater(...) method, to schedule a job for your EDT - Event Dispatcher Thread :-)Littlejohn
P
0

You're on the right track, but you're creating the frame's inside the loop, not outside. Here's what it should be like:

private void printWords() {
    JFrame frame = new JFrame("Run Text File"); 
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    JLabel textLabel = new JLabel("", 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);

    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();
        }
        textLabel.setTest(w.name);
    }
}
Pterous answered 30/10, 2011 at 8:16 Comment(2)
-1 : this won't work, because the EDT will be frozen until the last word is displayed, and only this last word will appear at the end.Sfax
@JBNizet — Ah, good point. Wasn't thinking when I wrote this.Pterous

© 2022 - 2024 — McMap. All rights reserved.