【问题标题】:My JLabel don't refresh quickly. Why?我的 JLabel 不会快速刷新。为什么?
【发布时间】:2016-04-14 23:18:01
【问题描述】:

我正在使用 vlcj 阅读媒体,我想在一些 JLabel 中显示经过的时间和剩余时间。我写了一些代码,但我的 JLabel.setText 似乎每秒刷新不超过 2 次。

为了进行更多尝试并确保不是 vlcj 的线程会出现问题,我用 JLabel 编写了一个非常代码。这个简单代码的目的是每秒更新 JLabel 10 次。

这是我的代码:

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import javax.swing.JFrame;
import javax.swing.JLabel;

public class TestLabel extends JFrame implements Runnable{
JLabel label = new JLabel("0");
int i=0;
TestLabel() {
    this.setTitle("Test");
    this.setSize(200, 200);
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    this.setContentPane(label);
    this.setVisible(true);      
}

public static void main(String[] args) {
    TestLabel tLabel = new TestLabel();
    Thread t1 = new Thread(tLabel);
    t1.start();
}

@Override
public void run() {
    ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
    scheduler.scheduleAtFixedRate(new Runnable() {
        @Override
        public void run() {
            i+=1;
            System.out.println(i);
            label.setText(String.valueOf(i));               
        }           
    }, 0, 100, TimeUnit.MILLISECONDS);      
}
}

结果:在控制台中,我得到 1、2、3、4... 但在 JLabel 中,我有类似:1、2、3 (...) 32、37、42、47。它似乎 System.out.println 写了每个“i”,但 JLabel 没有。为什么我有这个神器?

感谢您的所有回复。问候。

【问题讨论】:

    标签: java jlabel java-threads


    【解决方案1】:

    您需要在使用 Swing 时调用 SwingUtilities.invokeLater 方法来正确更新您的 GUI 文本(即 JFrameJLabel 等)。

    public void run() {
        i+=1;
        System.out.println(i);
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                label.setText(String.valueOf(i));               
            }           
        }); 
    }
    

    有关 SwingUtilities.invokeLater 的更多信息,请查看this SO 帖子。

    【讨论】:

      【解决方案2】:

      您不应使用来自事件调度线程以外的线程的摆动组件。

      因此,要么使用 Swing Timer 而不是 ScheduledExecutorService,要么将标签更改包装到 SwingUtilities.invokeLater()

      顺便说一句,对new TestLabel(); 的调用也应该包含在SwingUtilities.invokeLater() 中。阅读swing concurrency tutorial

      【讨论】:

      • 为英语课投票
      【解决方案3】:

      不要使用 ScheduledExecutorService。 Swing 组件需要在Event Dispatch Thread (EDT) 上更新。

      您应该使用Swing Timer。阅读 How to Use Timers 上的 Swing 教程部分了解更多信息。

      这是一个使用计时器的简单示例:How to make JScrollPane (In BorderLayout, containing JPanel) smoothly autoscroll。只需将间隔更改为 100,而不是 1000。

      【讨论】:

        猜你喜欢
        • 2022-11-27
        • 2015-11-01
        • 2015-07-10
        • 1970-01-01
        • 1970-01-01
        • 2019-09-22
        • 2010-11-17
        • 1970-01-01
        • 2014-08-02
        相关资源
        最近更新 更多