简体   繁体   中英

Swing GUI is not updating

I have simple Java Swing application which uses zip4j to encrypt and unpack zip file. 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. However, dots are being printed to console. How can I fix it to update that progress bar?

Please read Concurrency in 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. The EDT is meant for small operations on the GUI. You should never call Thread.sleep() on the EDT.

What you could do is make a Timer that would run your check every second until the check passes. That way the EDT would be free to not freeze.

A much better way of doing this is by using a 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)
  • 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()); in SwingUtilities.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. 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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