Java Swing GUI未更新

Java Swing GUI未更新,java,swing,event-dispatch-thread,Java,Swing,Event Dispatch Thread,我有一个简单的JavaSwing应用程序,它使用zip4j加密和解压zip文件。这是由这部分代码完成的: ZipFile zipFile = new ZipFile("dataStorage.zip"); zipFile.setPassword(password); zipFile.setRunInThread(true); ProgressMonitor progressMonitor = zipFile.getProgressMonitor(); if (!verify(zipFile))

我有一个简单的JavaSwing应用程序,它使用zip4j加密和解压zip文件。这是由这部分代码完成的:

ZipFile zipFile = new ZipFile("dataStorage.zip");
zipFile.setPassword(password);
zipFile.setRunInThread(true);
ProgressMonitor progressMonitor = zipFile.getProgressMonitor();
if (!verify(zipFile)) {
    JOptionPane.showMessageDialog(null, "You have entered incorrect password!", "ERROR", 0);
    return;
}
zipFile.extractAll("./"); //runs in new thread
//After entering this while GUI freezes
while (progressMonitor.getState() == ProgressMonitor.STATE_BUSY) {
    System.out.print("."); // this works normally...
    try {
        Thread.sleep(1000);
    } catch (InterruptedException ex) {
    //
    }
    pbEncryptionProgress.setValue(progressMonitor.getPercentDone()); //this is not updating progress bar, but getPercentDone is returning correct data
}

问题是进度条没有被更新。应用程序GUI似乎已冻结。然而,圆点被打印到控制台上。如何修复它以更新进度条?

包装调用
pbEncryptionProgress.setValue(progressMonitor.getPercentDone())SwingUtilities.invokeAndWait中的code>

您正在做的是通过睡眠和更新来使用EDT的所有资源,而不是留出任何时间让它实际重新绘制您的GUI。EDT用于GUI上的小型操作。您应该永远不要在EDT上调用
Thread.sleep()

你所能做的就是制作一个
计时器
,它将每秒运行一次检查,直到检查通过。这样EDT就可以自由地不冻结

更好的方法是使用
SwingWorker
。它有一些方法可以完成您的特定任务:

  • 要在后台执行的任务(在您的案例中-解压)
  • 将部分结果发布到GUI的方法(在您的情况下为%done)
  • 对部分结果作出反应的方法(在您的案例中-更新进度)
  • 完成时要调用的方法(在您的案例中未显示,但无论如何都很有用)

您不应该在event dispacher线程上执行压缩操作(这是所有事件处理发生的地方)。创建一个
SwingWorker
或类似的工具,将繁重的任务转移到一个单独的处理线程上,然后通知进度条,该进度条可以在EDT上更新。对于您的解决方案,只有在EDT再次空闲时,即zip操作完成后,才能处理对进度条的所有更新。

这可能会有所帮助。错误:无法从事件分派器线程调用invokeAndWait
,然后不要使用thread.sleep()来避免事件分派器线程阻塞。改为定义javax.swing.Timer,并在计时器的actionPerformed()中更新进度call@StanislavL也许他/她是对的,调用EANDWAIT不应该从EDT中调用???,否则重新绘制经理是对的***/blocked@mKorbel从方法的javadoc来看,当应用程序线程需要更新GUI时,应该使用此方法。不应从事件调度线程调用它。