java 如何在线程内更新 JFrame 标签?- 爪哇

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4250406/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 05:31:53  来源:igfitidea点击:

How to update JFrame Label within a Thread? - Java

javauser-interfacejframe

提问by Zeveso

I have tried a lot, but can't seem to get it to work.

我已经尝试了很多,但似乎无法让它发挥作用。

I was told to use EDT with the following example.

我被告知在以下示例中使用 EDT。

    SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            //  Modify the GUI here
        }
});

I have read on this topic a lot and still don't understand. I get what a thread is, but the .invokeLater still makes no sense to me. Honestly if you can explain in detailthis it would be a big help!

我已经阅读了很多关于这个主题的内容,但仍然不明白。我知道线程是什么,但 .invokeLater 对我来说仍然没有意义。老实说,如果你能详细解释一下这将是一个很大的帮助!

Goal of Program:To get the randomly generated key that is constantly created every second to update itself afterward in the GUI.

程序目标:获取每秒不断创建的随机生成的密钥,然后在 GUI 中进行自我更新。

采纳答案by John Vint

So there is an EDT (Event Dispatch Thread). All actions that appear on your screen are executed by the EDT. There is only one EDT per Swing application.

所以有一个 EDT(事件调度线程)。屏幕上显示的所有操作均由 EDT 执行。每个 Swing 应用程序只有一个 EDT。

You are in some arbitrary thread and you want to update the GUI through that thread? Well like I said there is only one EDT for each swing application, so you have to tell that EDT to display the label (or whatever context you want).

您在某个任意线程中并且想要通过该线程更新 GUI?就像我说的,每个 Swing 应用程序只有一个 EDT,因此您必须告诉 EDT 显示标签(或您想要的任何上下文)。

The idea here, is you push this Runnable onto a queue that the EDT pulls from. Eventually, your runnable will be processed by the EDT when all other actions before it are completed.

这里的想法是将这个 Runnable 推送到 EDT 从中提取的队列中。最终,您的 runnable 将在完成之前的所有其他操作时由 EDT 处理。

回答by Cesar

I recommend you get the book Filthy Rich Clients. There's a chapter where they explain Swing's threading model to great detail.

我建议您阅读肮脏的富客户这本书。他们有一章详细解释了 Swing 的线程模型。

Basically in Swing, any code that modifies the GUI should be executed in the Event Dispatcher Thread. The SwingUtilitiesclass that you are using there provides you with an easy way to post events to the event queue that is then dispatched by the EDT. That's what the invokeLatermethod does, it takes a new Runnable()as argument which is ultimately executed on the EDT.

基本上在 Swing 中,任何修改 GUI 的代码都应该在 Event Dispatcher Thread 中执行。SwingUtilities您在那里使用的类为您提供了一种将事件发布到事件队列的简单方法,然后由 EDT 调度。这就是该invokeLater方法所做的,它接受一个new Runnable()最终在 EDT 上执行的参数。

From the book:

从书中:

The invokeLater() implementation takes care of creating and queuing a special event that contains the Runnable. This event is processed on the EDT in the order it was received, just like any other event. When its time comes, it is dispatched by running the Runnable's run() method.

invokeLater() 实现负责创建和排队包含 Runnable 的特殊事件。该事件在 EDT 上按照接收顺序进行处理,就像任何其他事件一样。当它到来时,它会通过运行 Runnable 的 run() 方法来调度。

回答by JOTN

This is a pretty common element of all GUI programming. You have one thread that handles drawing the GUI, getting input, and running callbacks. If another thread tries to change the GUI related objects, it will conflict with the GUI thread. Say, for example, it was half way through drawing something and you change the color from a different thread.

这是所有 GUI 编程中非常常见的元素。您有一个线程来处理绘制 GUI、获取输入和运行回调。如果另一个线程试图改变 GUI 相关的对象,它将与 GUI 线程发生冲突。比如说,画了一半,你从不同的线程改变了颜色。

All invokeLater does is queue up something for the GUI thread to run. By "later" it's really runs almost instantly but the current thread doesn't have to wait for it. The GUI thread may be doing a draw or waiting for a callback to return which would delay executing the code you gave it.

invokeLater 所做的只是排队等待 GUI 线程运行。通过“稍后”,它实际上几乎立即运行,但当前线程不必等待它。GUI 线程可能正在执行绘制或等待回调返回,这会延迟执行您提供的代码。

回答by Tim Williscroft

Needs to be a member so we can change it and still use it from an inner class

需要成为成员,以便我们可以更改它并仍然从内部类中使用它

protected long secret=0;

... this needs to be in your code somewhere it'll get run...

......这需要在你的代码中它会运行......

JFrame f = new JFrame("foo");
new Thread(){
        public void run() {
            for(;;){
                try { 
                    sleep(1000);
                } catch Interrupted (Exception ix){ 
                    return;
                }
                // TODO update your secret key here
                // please don't use random()

                SwingUtilities.invokeLater(new Runnable() {
                    public void run() {
                        f.setTitle("secret "+x);
                    }
                });
            }
        }
   }).start();

....

....

Only ever update Swing from the EDT so that it paints properly.

只从 EDT 更新 Swing,以便它正确绘制。

When you are in the EDT ( running code in an event handler) you can call paintImmediately() if you really must.

当您在 EDT 中(在事件处理程序中运行代码)时,如果确实需要,您可以调用paintImmediately()。

回答by Courtney Christensen

If you're all looking to do is update the UI on a known schedule, try something like the following. This assumes that a JFrameis the component you wish to update every 1 second.

如果您只想按照已知的时间表更新 UI,请尝试以下操作。这假设 aJFrame是您希望每 1 秒更新一次的组件。

private static final int WAIT_LENGTH = 1000; // 1 second
private JFrame frame = new JFrame();

// Thread will update the UI (via updateUI() call) about every 1 second
class UIUpdater extends Thread {
  @Override
  void run() {
    while (true) {
      try {
        // Update variables here
      }
      catch (Exception e) {
        System.out.println("Error: " + e);
      }
      finally {
        frame.repaint();
        Thread.sleep(WAIT_LENGTH);
      }
    }
  }
}

To start this thread:

要启动此线程:

UIUpdater t = new UIUpdater();
t.start();