由java中的另一个线程刷新GUI(swing)

Posted

技术标签:

【中文标题】由java中的另一个线程刷新GUI(swing)【英文标题】:Refreshing GUI by another thread in java (swing) 【发布时间】:2011-11-05 22:55:56 【问题描述】:

我有一个主程序,其中 GUI 基于摇摆,根据四种状态之一,GUI 元素具有不同的参数。

public class Frame extends JFrame implements Runnable 
Status status = 1;
...
@Override
public void run() 
    switch (status) 
        case 1:
        ...
        case 2:
        ...


public void updateGUI(Status status) 
   this.status = status;
   SwingUtilities.invokeLater(this);

如果我想刷新 GUI,只调用带有适当参数的 updateGUI,一切都很好。但是该程序还创建了一个额外的线程,在处理相关数据后应该更改 GUI 主程序。不幸的是我不能在这个线程中调用方法 updateGUI (..)。

我知道我可以使用invokeLater或者SwingWorker来刷新但是有10多个元素所以我宁愿使用方法udpateGUI()。

如有任何提示,我将不胜感激。

【问题讨论】:

请看一下这个问题中关于事件和事件总线的答案:***.com/questions/7131484/… 为什么不能从其他线程调用updateGUI?除了对状态变量的非同步访问之外,我不明白为什么您不能从其他线程使用此方法。 如果我调用 Frame f = new Frame(); f.udpateGUI(..);然后当然什么也没发生。我还能如何调用该方法? 将要更新的框架传递给您的后台任务(例如在其构造函数中) 【参考方案1】:

这里有一个小sn-p,您可以添加到方法中以确保它在GUI 线程中执行。它依赖于isEventDispatchThread()

public void updateGUI(final Status status) 
   if (!SwingUtilities.isEventDispatchThread()) 
     SwingUtilities.invokeLater(new Runnable() 
       @Override
       public void run() 
          updateGUI(status);
       
     );
     return;
   
   //Now edit your gui objects
   ...

【讨论】:

【参考方案2】:

如果您使status 字段线程安全,那么您可以直接从后台线程调用setStatus。要使状态线程安全,请将更改放在同步块中,并使变量 volatile 以便其他线程上的更新可见。

例如

public class Frame extends JFrame implements Runnable 
private volatile Status status = 1;
...
@Override
public void run() 
    switch (status) 
        case 1:
        ...
        case 2:
        ...


public void updateGUI(Status status) 
   setStatus(status);
   SwingUtilities.invokeLater(this);


private synchronized void setStatus(Status status) 
   this.status = status;

有了这些更改,就可以从任何线程调用setStatus

【讨论】:

以上是关于由java中的另一个线程刷新GUI(swing)的主要内容,如果未能解决你的问题,请参考以下文章

Swing理解Swing中的事件与线程

怎样使用java swing画一个表格,把输出显示到表格上,而且每10秒自动刷新一次

如何从 Java 中的另一个线程更新 SWT GUI

Swing:关于Java界面编程的第一课,如何正确的处理界面中的线程

java swing编程:如何刷新动态显示的内容并生成滚动条显示

Java Swing 线程:执行逻辑命令时 GUI 挂起