如何从Thread更新java GUI?
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); } } }
我有两个具有共享队列的类。 其中一个是Producer,它生成直到一个目标,另一个消耗这些元素。 所有两个都扩展了Thread。 我想向用户显示进度百分比,但它会冻结我的GUI,所以我该怎么办?
-
默认情况下,
Worker Threads
永远不会调用EventDispatchThread
,你Concurency in Swing
遇到Concurency in Swing
问题 -
Swing GUI的所有更新必须在EDT上完成
-
Runnable
可能是正确的方法,但ProgressPrecent.setValue(Producer.ProgressPercent);
必须包装在invokeLater
码
SwingUtilities.invokeLater(new Runnable(){ public void run(){ ProgressPrecent.setValue(Producer.ProgressPercent); } });
- 删除EDT测试,
代码行
if(EventQueue.isDispatchThread()) { r.run(); }
通过defaut Workers Thread
永远不会调用EDT,然后从EDT启动无关紧要,也不测试isDispatchThread()
不会让我有所作为
-
从来没有,不要在
Swing Listeners
使用Thread.sleep(int
),因为它也导致了Swing GUI的冻结 -
我想你也可以使用SwingWorker来完成这项工作
我认为你必须把整个while循环放到一个线程中。 否则循环将阻止您的ActionEvent,从而冻结UI。
就像是:
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();