进入循环前显示GlassPane

TV.*_*TV. 3 java swing glasspane order-of-execution

(在带有Swing GUI的应用程序中)我想在以循环或方法执行的某些工作中显示GlassPane,这是在单击JButton之后调用的。

例如:(单击按钮后执行的操作)

if (item.equals(button)) {

    glassPane.setVisible(true);

    someTimeConsumingMethod();

    glassPane.setVisible(false);

}
Run Code Online (Sandbox Code Playgroud)

运行此代码会导致在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).

}
Run Code Online (Sandbox Code Playgroud)

第一个更改的要点是,在我的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);
        }
    });

}
Run Code Online (Sandbox Code Playgroud)

它不能像UPDATE1中的代码那样工作(但仍然可以工作)。问题是:

  • glassPane加载时不带有.gif动画(文件在自定义glassPane类中设置-适用于UPDATE1代码)

  • 在“工作”过程结束时会有很小的延迟-第一个光标更改为正常状态(从WAIT_CURSOR开始),并且在很短的时间后glassPane消失了。激活/停用时,可通过自定义glassPane类更改光标(使用新的Thread方式不会延迟)。

使用SwingWorker的invokeLater方法是否正确?

编辑:我的错误,我将SwingWorker与SwingUtilities.invokeLater()混淆了。我猜图像问题是由于someTimeCOnsumingMethod启动时GUI冻结所致。

mKo*_*bel 5

在显示结果之前,GUI只是冻结了片刻。删除该循环中的最后一行(glassPane.setVisible(false);)会在方法完成后(GUI冻结时)显示glassPane。

这是一个常见的问题Event Dispath Thread,当所有事件EDTSwing GUI在同一时间刷新到时,该方法中的所有操作if (item.equals(button)) {都可以在同一时间完成,

但是您的描述说您在Swing中遇到了Concurency的问题,某些代码阻止了EDT,这是一个很小的延迟,例如Thread.sleep(int)可能导致此问题,不这样做,或者将代码块重定向到Backgroung任务

有没有简单的方法可以在GUI冻结之前显示glassPane,还是在这里需要使用一些高级知识?(线程?)

这个问题是预订示例为什么SwingWorker在那里,或更简单的方法是Runnable#Thread

  • SwingWorker完全保证在EDT上完成输出的方法

  • 来自Runnable#ThreadSwing GUI的任何输出都应包装在其中invokeLater()

最简单的步骤Jbuttons Action可能是

  • 显示 GlassPane

  • 从启动后台任务SwingWorker(确保通过监听PropertyChangeListener)或调用Runnable#Thread

  • 在这一刻ActionListener执行完成,其余代码被重定向到Backgroung taks

  • 如果任务结束,则隐藏 GlassPane

  • 通过包装setVisibleinvokeLater()来创建简单的空隙Runnable#Thread

  • 如果您使用,SwingWorker则可以从中隐藏GlassPaneon正确的事件,PropertyChangeListener也可以使用任何(单独的)空白来隐藏GlassPane

@camickr编写的GlassPane最佳代码,或者基于该代码我的问题