【问题标题】:Update JLabel every X seconds from ArrayList<List> - Java每 X 秒从 ArrayList<List> 更新 JLabel - Java
【发布时间】:2011-12-18 02:51:26
【问题描述】:

我有一个简单的 Java 程序,它读入一个文本文件,用“”(空格)分割它,显示第一个单词,等待 2 秒,显示下一个……等等……我想做这个在 Spring 或其他一些 GUI 中。

关于如何使用 spring 轻松更新单词有什么建议吗?遍历我的列表并以某种方式使用 setText();

我没有运气。我正在使用这种方法在控制台中打印出我的单词并将 JFrame 添加到其中...在控制台中效果很好,但会输出无穷无尽的 jframe。我在网上找到了大部分。

    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);
        }
    }

我有一个使用 JFrame 和 JLable 创建的窗口,但是,我希望静态文本是动态的,而不是加载新的弹簧窗口。我想它闪一个字,消失,闪一个字消失。

关于如何更新 JLabel 有什么建议吗?重绘()的东西?我正在画一个空白。

谢谢!

更新: 在下面好心人的帮助下,我已将其正确打印到控制台。这是我的打印方法:

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();

    }

但是,它没有更新标签?我的构造函数看起来像:

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...");

}

到达那里...一旦我或任何帮助我的人得到它的工作,我将发布修复程序。再次感谢!

【问题讨论】:

  • 题外话:你的头像,叫什么?我到处都能看到它,但找不到它的名字。
  • 嗨 Martinjn,它被称为二维码:en.wikipedia.org/wiki/QR_code
  • "spring window"是什么意思?对我来说,这似乎是一个 HTML 弹出窗口。
  • @buildakicker :你混淆了 Spring(一个 IOC 框架等等)和 Swing(Java 的标准桌面 GUI 框架)
  • 我在做梦吗,嗯,也许昨天是喝酒的一天,不,不要在 Swing 代码中使用 Thread.sleep(int),因为阻塞 EDT,请参阅我的帖子 @JB Nizet +++++ +++++++++++++++++++++++++++++++++++++++++++++++

标签: java swing concurrency timer freeze


【解决方案1】:

首先,构建并显示您的 GUI。显示 GUI 后,使用 javax.swing.Timer 每 500 毫秒更新一次 GUI:

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();

【讨论】:

  • 我为此快疯了。我只是不明白如何让计时器更新文本。我可以用字符串数组做到这一点,但由于某种原因,当我尝试读取文件时,所有中断......
  • GUI 代码不应该直接读取文件。读取内存中的整个文件,将其内容存储在内存中的列表中,然后使用上面的代码(当然,除非文件真的太大而无法放入内存)。
  • 不是很大。最多约2000字。所以应该是这样的:public class TText{Declare VARS;SHOW GUI{}GET TEXT IN{}PRINT TEXT OUT{}ACTIONLISTENER with TIMER updates GUI{}}看起来对吗?
  • 好的,终于让它工作起来了……它现在打印到控制台。但是,还没有更新 label.setText() ......更接近!
【解决方案2】:

永远不要在 Swing 代码中使用Thread.sleep(int),因为它会阻塞 EDT;更多here,

使用Thread.sleep(int)的结果是这样的:

Thread.sleep(int) 结束时

示例代码:

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;
    }
}

【讨论】:

  • @Andrew Thompson 我分享了你的好主意,但是 void convertToFromBytes 工作很奇怪。没有其他方法如何将 Graphics2D 转换为普通图像文件
  • +1 我冒昧地重构了您的指导性示例。
  • @trashgod 谢谢!,因为我创建了这个快速编码示例长达 10 分钟,你的编码技巧/维度仍然在我的新手头脑中错过了某个地方,真的我必须开始学习如何编写代码(我不能' t 拒绝来自 RPG/Cobol 的错误编程习惯)
  • @trashgod 我在全屏尺寸(2x FullHd 显示器)上尝试了你的更改,这些东西是为了保护世界免受愚蠢,再次感谢你
  • @mKorbel : 我要在这段代码中学习很多新东西,你在 Swing 中真的太好了 :-)
【解决方案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); 

    }
}

我得到它与这段代码一起工作...希望它可以帮助其他人扩展他们的 Java 知识。另外,如果有人对清理这个有任何建议。请这样做!

【讨论】:

  • +1,只是一个小建议,您的 main 方法的内容,必须包含在 SwingUtilities.invokeLater(...) 方法中,以便为您的 EDT - 事件调度程序线程安排工作:-)跨度>
【解决方案4】:

您在正确的轨道上,但您是在循环内部而不是外部创建框架。应该是这样的:

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);
    }
}

【讨论】:

  • -1 :这不起作用,因为 EDT 将被冻结,直到显示最后一个单词,并且只有最后一个单词才会出现在末尾。
  • @JBNizet — 啊,好点子。写这篇文章的时候没想到。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-06-13
  • 1970-01-01
  • 2012-06-18
  • 2014-07-20
  • 1970-01-01
  • 2012-08-03
  • 1970-01-01
相关资源
最近更新 更多