如何从线程更新 Java GUI?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13543345/
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-31 13:09:55  来源:igfitidea点击:

How to update java GUI from Thread?

javaswing

提问by Alyafey

 private void StartActionPerformed(java.awt.event.ActionEvent evt) {

        Queue queue=new Queue();
        int target=Integer.parseInt(Target.getText());
        String path=Path.getText();
        final Producer p=new Producer(queue, target);
        Consumer c=new Consumer(queue);
        p.start();
        c.start();

        while(p.finish !=true)
        {
          Runnable r = new Runnable() {
            public void run() {
              ProgressPrecent.setValue(Producer.ProgressPercent);
            }
          };
          if(EventQueue.isDispatchThread()) {
            r.run();
          }
          else {
            EventQueue.invokeLater(r);
          }
       }
 }

I have two classes that have a shared Queue. one of them is Producer that produces till a target other one consume those elements. all of two extends Thread. I want to display the progress percent to the user, but it freeze my GUI so what should I do?

我有两个具有共享队列的类。其中之一是生产者,直到另一个目标消耗这些元素。两个都扩展了线程。我想向用户显示进度百分比,但它冻结了我的 GUI,我该怎么办?

回答by morja

I think you will have to put the whole while loop into a thread. Otherwise the loop will block your ActionEvent and thus freezes the UI.

我认为您必须将整个 while 循环放入一个线程中。否则循环将阻止您的 ActionEvent 并因此冻结 UI。

Something like:

就像是:

new Thread(){
    public void run(){
        while(!p.finish){
           SwingUtilities.invokeLater(new Runnable(){
             public void run(){
               ProgressPrecent.setValue(Producer.ProgressPercent);
             }
           }); 
           try{
              Thread.sleep(100);
           }catch(...){}
        }
    }
}.start();

回答by mKorbel

  • Worker Threadsby default never to invoked EventDispatchThread, you have issue with Concurency in Swing

  • all updates to Swing GUI must be done on EDT

  • Runnablecould be proper way but ProgressPrecent.setValue(Producer.ProgressPercent);must be wrapped in invokeLater

  • Worker Threads默认情况下从不调用EventDispatchThread,您有问题Concurency in Swing

  • Swing GUI 的所有更新都必须在 EDT 上完成

  • Runnable可能是正确的方式,但ProgressPrecent.setValue(Producer.ProgressPercent);必须包裹在invokeLater

code

代码

SwingUtilities.invokeLater(new Runnable(){
    public void run(){
        ProgressPrecent.setValue(Producer.ProgressPercent);
    }
}); 
  • remove testing for EDT,
  • 删除 EDT 测试,

code lines

代码行

if(EventQueue.isDispatchThread()) {
   r.run();
}

Workers Threadby defaut never ever to invoke EDT, then doesn't matter if is started from EDT, nor tested for isDispatchThread()doesn't make me some sence

Workers Thread默认情况下永远不会调用 EDT,那么是否从 EDT 启动也没有关系,也没有经过测试对isDispatchThread()我没有意义

  • never ever, don't to use Thread.sleep(int) inside Swing Listeners, because caused freeze Swing GUI too

  • I think you can to use SwingWorker for this jobtoo

  • 永远不要Thread.sleep(int在里面使用) Swing Listeners,因为也会导致 Swing GUI 冻结

  • 我想你可以使用的SwingWorker这个工作