调用SwingWorker.get()时防止GUI冻结

我有一个程序,我正在加载一个文件,同时我正在显示一个窗口,通知用户该文件正在加载。 我决定创建一个FileLoader类,它实际上是处理文件的SwingWorker和实现PropertyChangeListener的ProgressWindow,以通知用户传递给它的SwingWorker的状态。

我的代码目前看起来像这样:

FileLoader loader = new FileLoader(filePath); new ProgressWindow(loader, "Loading File", "Loading File"); //ProgressWindow's constructor calls loader.execute() inherited from SwingWorker doc = loader.get(); //GUI Freezes when called 

问题在于每当我调用loader.get()时,它都会冻结GUI,因此进度窗口中的进度条不会运行,整个过程毫无意义。 据我所知,这是因为控制GUI的线程与调用loader.get()的线程相同,而loader.get()在loader.execute()运行时保持不变。

到目前为止,我已经尝试为loader.get()命令或loader.execute()方法创建一个新线程,并在线程上调用SwingUtilities.invokeLater(),但随后整个程序冻结。

我考虑过为SwingWorker.isDone()创建一个ChangeListener,然后运行loader.get(),但这需要对我的代码进行一些修改,而我宁愿不这样做。

谁能告诉我最好的办法是什么?

get()就像join()一样,它会在被调用之前阻塞,并在调用之前等待SwingWorker完成。 错误地使用它可以完全取消使用SwingWorker的所有优点。

解决方案:在您知道SwingWorker完成其处理之前,通过在SwingWorker的done()方法中调用它,或者如果您需要从调用代码调用它,然后在PropertyChangeListener中调用它,请不要调用get() 。当SwingWorker的“state”属性为SwingWorker.StateValue.DONE时,已添加到SwingWorker中。

就像是:

  final FileLoader loader = new FileLoader(filePath); loader.addPropertyChangeListener(new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { if ("state".equals(evt.getPropertyName())) { // since DONE is enum, no need for equals(...) method if (evt.getNewValue() == SwingWorker.StateValue.DONE) { try { loader.get(); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } } } } }); new ProgressWindow(loader, "Loading File", "Loading File"); 

注意:代码未编译也未经过测试

编辑:尝试/捕获添加。

到目前为止,我已经尝试为loader.get()命令或loader.execute()方法创建一个新线程,并在线程上调用SwingUtilities.invokeLater(),但随后整个程序冻结。

如果在将执行EDT中冻结GUI的线程的线程上调用SwingUtilities.invokeLater() 。 相反,通过调用它的start()方法运行该线程,并在需要更新PropertyChangeListener的进度条时仅使用SwingUtilities.invokeLater()

我已经创建了一个WorkerThread类来处理Threads和GUI current / main thread。 我已经将我的GUI应用程序放在WorkerThread的construct()方法中,当一个事件触发启动XXXServer然后所有线程被激活并且GUI工作没有冻结。 看一看。

 /** * Action Event * * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) */ public void actionPerformed(ActionEvent ae) { log.info("actionPerformed begin..." + ae.getActionCommand()); try { if (ae.getActionCommand().equals(btnStart.getText())) { final int portNumber = 9990; try { WorkerThread workerThread = new WorkerThread(){ public Object construct(){ log.info("Initializing the Server GUI..."); // initializing the Server try { xxxServer = new XXXServer(portNumber); xxxServer.start(); btnStart.setEnabled(false); } catch (IOException e) { // TODO Auto-generated catch block log.info("actionPerformed() Start button ERROR IOEXCEPTION..." + e.getMessage()); e.printStackTrace(); } return null; } };workerThread.start(); } catch (Exception e) { log.info("actionPerformed() Start button ERROR..." + e.getMessage()); e.printStackTrace(); } } else if (ae.getActionCommand().equals(btnStop.getText())) { log.info("Exit..." + btnStop.getText()); closeWindow(); } } catch (Exception e) { log .info("Error in ServerGUI actionPerformed===" + e.getMessage()); } }