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

gal*_*ica 8 java user-interface swing multithreading

我有一个主程序,其中GUI基于swing并且取决于四种状态之一,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);
}
Run Code Online (Sandbox Code Playgroud)

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

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

我会感激任何提示.

unh*_*ler 21

这是一个可以添加到方法的小片段,以确保它在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
   ...
}
Run Code Online (Sandbox Code Playgroud)


mdm*_*dma 10

如果您使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;
}
Run Code Online (Sandbox Code Playgroud)

有了这些变化,可以setStatus从任何线程调用.