(在我使用Swing GUI的应用程序中)我想在以循环或方法执行的某些工作中显示GlassPane,这是在单击JButton之后调用的。
例如:
(单击按钮后执行的操作)
if (item.equals(button)) {
glassPane.setVisible(true);
someTimeConsumingMethod();
glassPane.setVisible(false);
}
运行此代码会导致在someTimeConsumingMethod()执行期间未显示glassPane-GUI仅冻结了片刻,然后显示结果。删除该循环中的最后一行(glassPane.setVisible(false);)后,方法完成后(GUI冻结时)将显示glassPane。
有没有简单的方法可以在GUI冻结之前显示glassPane,还是在这里需要使用一些高级知识? (线程?)
UPDATE1:
我已经根据 davidXYZ 答案(有两个更改)更新了代码:
(单击按钮后执行的操作)
if (item.equals(button)) {
glassPane.setVisible(true);
new Thread(new Runnable(){
public void run(){
someTimeConsumingMethod(); // 1st change: running the someTimeConsumingMethod in new Thread
// instead of setting glassPane to visible
}
}).start();
// 2nd change: moved glassPane.setVisible(false); inside the someTimeConsumingMethod(); (placed at the end of it).
}
第一个更改的要点是,在我的GUI线程中运行someTimeConsumingMethod之前,将glassPane设置为在新线程中可见,是在someTimeConsumingMethod完成之后再次显示了glassPane(对此进行了双重检查)。
现在工作正常,谢谢您的所有回答。我一定会检查您提供的所有链接以真正理解线程!
UPDATE2:
更多信息:someTimeConsumingMethod();在我的应用程序中,是根据XML数据预装新的Swing组件(从JButtons和JLabel构建的卡,其中需要的JPanel很少,并在正确的位置添加它们)。
UPDATE3:
我正在尝试使用SwingWorker的invokeLater方法使其工作。现在看起来像这样:
(单击按钮后执行的操作)
if (item.equals(button)) {
glassPane.setVisible(true);
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
someTimeConsumingMethod();
glassPane.setVisible(false);
}
});
}
作为 UPDATE1 中的代码,它的效果不佳(但仍然有效)。问题是:
激活/停用时,可通过自定义glassPane类更改光标(使用新的Thread方式不会延迟)。
使用SwingWorker的invokeLater方法是否正确?
编辑:我的错误,我将SwingWorker与SwingUtilities.invokeLater()混淆了。我猜图像问题是由于someTimeCOnsumingMethod启动时GUI冻结所致。
最佳答案
在显示结果之前,GUI只是冻结了片刻。删除该循环中的最后一行(glassPane.setVisible(false);)后,方法完成后(GUI冻结时)将显示glassPane。
这是关于Event Dispath Thread
的常见问题,当一刻将EDT
中的所有事件刷新到Swing GUI
时,那么if (item.equals(button)) {
方法中的所有操作都可以在一瞬间完成,
但是您的描述说您在Swing中的Concurency遇到了问题,一些代码阻止了EDT,这是一个很小的延迟,例如Thread.sleep(int
)可能会导致此问题,不要这样做,或者将代码块重定向到Backgroung任务
有没有简单的方法可以在GUI冻结之前显示glassPane,还是在这里需要使用一些高级知识? (线程?)
这个问题是预订示例,为什么存在SwingWorker
,或更简单的方法是Runnable#Thread
在SwingWorker
中实现的
Runnable#Thread
到Swing GUI的任何输出都应包装在invokeLater()
中从
Jbuttons Action
最简单的步骤可能是GlassPane
SwingWorker
启动后台任务(请确保通过PropertyChangeListener
监听)或调用Runnable#Thread
ActionListener
执行,其余代码重定向到Backgroung taks GlassPane
setVisible
包装到invokeLater()
中为Runnable#Thread
如果您使用
SwingWorker
,则可以使用GlassPane
中隐藏适当事件时的PropertyChangeListener
,也可以使用任何(单独的)空位来隐藏GlassPane
GlassPane by @camickr或我的question about based on this code的最佳代码