简体   繁体   English

Swing GUI 未更新

[英]Swing GUI is not updating

I have simple Java Swing application which uses zip4j to encrypt and unpack zip file.我有一个简单的 Java Swing 应用程序,它使用 zip4j 来加密和解压 zip 文件。 It's done by this part of code:是由这部分代码完成的:

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
}

Problem is that progress bar is not being updated.问题是进度条没有更新。 Application GUI seems frozen.应用程序 GUI 似乎冻结了。 However, dots are being printed to console.但是,点正在打印到控制台。 How can I fix it to update that progress bar?如何修复它以更新该进度条?

Please read Concurrency in Swing .请阅读Swing 中的并发

What you are doing is using up all resources of the EDT by sleeping and updating, not leaving any time for it to actually redraw your GUI.您正在做的是通过休眠和更新来耗尽 EDT 的所有资源,而不是留出任何时间实际重绘您的 GUI。 The EDT is meant for small operations on the GUI. EDT 适用于 GUI 上的小型操作。 You should never call Thread.sleep() on the EDT.永远不应该在 EDT 上调用Thread.sleep()

What you could do is make a Timer that would run your check every second until the check passes.您可以做的是制作一个Timer ,它会每秒运行一次检查,直到检查通过为止。 That way the EDT would be free to not freeze.这样 EDT 就可以自由地不冻结。

A much better way of doing this is by using a SwingWorker .这样做的更好的方法是使用SwingWorker It has methods that do your specific thing:它有做你特定事情的方法:

  • A task to do in the background (In your case - unzip)在后台执行的任务(在您的情况下 - 解压缩)
  • A method to publish a partial result to the GUI (in your case % done)一种将部分结果发布到 GUI 的方法(在您的情况下完成百分比)
  • A method to react to partial results (In your case - update progress)对部分结果做出反应的方法(在您的情况下 - 更新进度)
  • A method to invoke when done (Not shown in your case, but useful anyway).完成后调用的方法(在您的情况下未显示,但无论如何都很有用)。

Wrap the call pbEncryptionProgress.setValue(progressMonitor.getPercentDone());包装调用pbEncryptionProgress.setValue(progressMonitor.getPercentDone()); in SwingUtilities.invokeAndWaitSwingUtilities.invokeAndWait

You shouldn#t do your zipping on the event dispacher thread (which is where all your event-handling takes place).你不应该在事件调度器线程(这是所有事件处理发生的地方)上进行压缩。 Create a SwingWorker or someething like it to offload your heavy duty on a separate processing thread that can then inform the progress bar that can be updated on the EDT.创建一个SwingWorker或类似的东西,以在单独的处理线程上卸载繁重的工作,然后可以通知可以在 EDT 上更新的进度条。 With your solution all updates to the progress bar can only be processed when the EDT is free again, that is after your zip-operation is finished.使用您的解决方案,进度条的所有更新只能在 EDT 再次空闲时处理,即在您的 zip 操作完成后。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM