2011-02-07 176 views
8

在Swing上执行一些操作后更新UI的正确方法是什么?Swing,如何正确更新UI

例如,点击一个按钮后,调用的方法可能几乎是即时的或需要几秒钟的时间。实际上,所有应用程序逻辑都是通过Web服务远程完成的,所以等待应用程序响应是正常的。

我的一个按钮的事件处理程序可能看起来像这些:

myButton.addActionListener(new java.awt.event.ActionListener() { 
    public void actionPerformed(java.awt.event.ActionEvent evt) { 
     //callWebService(); 
     //do stuff 
     //updateUI(); // <----- repaint? revalidate? what? 
    } 
}); 

我目前的实现调用updateUI方法,内部调用的validate()和重绘()为保存UI父组件。这有效,但有时我可以看到屏幕闪烁。我做错了吗?有没有更好的方法来做到这一点?

+0

http://en.wikipedia.org/wiki/SwingWorker – qwerty 2011-02-07 11:58:43

+0

据我了解,这个问题是关于做一些更新后的UI,不是在另一个线程做的东西,以保持UI响应。不过,我不完全明白为什么在问题中提到方法的执行时间。 – 2011-02-07 12:15:20

+0

我提到了执行时间,因为它看起来像Swing在尝试加载组件时的行为有点不同,并且加载时间过长,因此可能需要重新绘制屏幕。 – Hectoret 2011-02-07 12:25:29

回答

0

您通常不应做任何事情:如果你使用Swing组件的方法,或他们的模型的方法,必要的事件被解雇和GUI应自动更新。

这会不会是这样,如果你定义自己的模型(而忘记火必要的事件,但当时它在你的模型中的错误,并应固定在那里。

1

采取长期运行将事件发送回AWT事件调度线程(EDT)以更新GUI,使用java.awt.EventQueue.invokeLater

5

正确的方法是使用SwingWorker,但如果要手动执行,您将拥有实施以下模式:

@Override public void actionPerformed(java.awt.event.ActionEvent evt) { 
    new Thread() { 
    @Override public void run() { 
     //callWebService(); 
     //do stuff 
     SwingUtilities.invokeLater(new Runnable(){ 
     @Override public void run() { 
      //updateUI(); // <----- repaint? revalidate? what? 
     } 
     }); 
    } 
    }.start(); 
} 

对于重绘/重新验证问题,通常请拨revalidate(),然后repaint()。这当然只适用于手动绘制的组件。对于您重复使用的组件,只需调用其值更改方法即可。

4

我个人使用的SwingWorker为此,尽管有一些其他的意见/回答:

  • 尽管保持UI响应不是原来的问题的一部分,这是很好的做法,这样做反正(我想不出一个很好的理由,锁定了EDT冗长的处理。)
  • 它提供了一个done()方法可以实现,这将在美国东部时间默认情况下,当任务完成后执行,节省需要手动包装的东西在invokeLater()
  • 这是更ex这种框架可以提供一个框架,以允许稍后添加进度等信息,只要它是如此需要的话。

最近我见过很多SwingWorker讨厌,我不明白为什么。这是一个设计良好,可扩展的类,专门用于诸如此类的用途。是的,你可以用线程包装并启动它们,让它们将其他方法包装在invokeLater()中,但为什么在有更好的免费版本时重新发明轮子?