我有一个程序,我正在加载文件,同时我正在显示一个窗口,通知用户文件正在加载。我决定创建一个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.execute()运行时,该线程会被保留。
到目前为止,我已经尝试为loader.get()命令或loader.execute()方法创建一个新线程,并在线程上调用SwingUtilities.invokeLater(),但随后整个程序冻结。
我考虑过为SwingWorker.isDone()创建一个ChangeListener,然后运行loader.get(),但这需要对我的代码进行一些修改,而我宁愿不做。
有人能告诉我最好的方法是让它发挥作用吗?
答案 0 :(得分:6)
get()
与join()
类似,它会在被调用之前阻塞,并等待SwingWorker在被调用之前完成。错误地使用它可以完全取消使用SwingWorker的所有优点。
解决方案:在您知道SwingWorker完成其处理后,通过在SwingWorker的get()
方法中调用它,或者如果您需要从调用中调用它,请不要调用done()
代码,然后在SwingWorker的“state”属性为SwingWorker.StateValue.DONE时已添加到SwingWorker的PropertyChangeListener中。
类似的东西:
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");
注意:代码未编译也未经过测试
编辑:尝试/捕捉添加。
答案 1 :(得分:3)
到目前为止,我已经尝试为loader.get()命令或loader.execute()方法创建一个新线程,并在线程上调用SwingUtilities.invokeLater(),但随后整个程序冻结。
如果在将执行EDT中冻结GUI的线程的线程上调用SwingUtilities.invokeLater()
。相反,通过调用它的start()
方法运行该线程,并在需要更新SwingUtilities.invokeLater()
中的进度条时仅使用PropertyChangeListener
。
答案 2 :(得分:0)
我创建了一个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());
}
}