在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()和repaint()到保存UI的父组件。这有效,但有时我可以看到屏幕闪烁。我做错了吗?有没有更好的方法呢?
答案 0 :(得分: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()
。当然,这仅对您手动绘制的组件有效。对于您重复使用的组件,只需调用它们的值更改方法。
答案 1 :(得分:4)
我个人使用SwingWorker,尽管其他一些评论/答案:
done()
方法,可以在任务完成后默认在EDT上执行,省去了在invokeLater()
中手动包装内容的需要我最近看到很多SwingWorker讨厌,我不明白为什么。它是一个设计精美,可扩展的类,专门用于这样的目的,效果很好。是的,你可以在线程中包装并启动它们并让它们在invokeLater()
中包含其他方法,但是为什么在有更好的免费提供时重新发明轮子呢?
答案 2 :(得分:1)
将长时间运行的任务带到另一个线程。将事件发送回AWT事件调度线程(EDT)以使用java.awt.EventQueue.invokeLater
更新GUI。
答案 3 :(得分:0)
您通常不必做任何事情:如果您使用swing组件方法或其模型的方法,则会触发必要的事件并且GUI应自动更新。
如果您定义自己的模型(并且忘记触发必要的事件,但是这是模型中的错误,那么就不会出现这种情况,并且应该在那里修复。