我有一个主类Gui
来处理我的GUI并调用一些SwingWorkers(调用DB和其他数据源),这些类已放在他们自己的类TablesDataManager
中。我的问题是,当其中一个摇摆工作者在其done90方法(即在EDT)中抛出异常时,我希望能够在主类中以某种方式捕获它并相应地采取行动(在我的SSCCE中调用showErrorAndExit
)。
欢迎任何想法。
Gui.java
import java.awt.event.WindowEvent;
import javax.swing.*;
public class Gui extends JFrame {
private final JLabel waitLabel = new JLabel();
private final JPanel panel = new JPanel();
private final TablesDataManager tblData = new TablesDataManager();
/**
* @param args the command line arguments
*/
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
private static void createAndShowGui() {
Gui frame = new Gui("My Great GUI");
frame.setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
public Gui(String title) {
super(title);
panel.add(waitLabel);
setContentPane(panel);
try {
initData();
} catch (Exception e) {
showErrorAndExit(e);
}
}
//I WANT TO CALL THIS METHOD IF done() THROWS AN EXCEPTION
private void showErrorAndExit(Exception e) {
JOptionPane.showMessageDialog(this,
"An unexpected error occured while initialising the tables. The application will close.\n"
+ (e.getMessage() == null ? "" : e.getMessage()),
"Unrecoverable error",
JOptionPane.ERROR_MESSAGE);
this.dispatchEvent(new WindowEvent(this, WindowEvent.WINDOW_CLOSING));
}
private void initData() {
waitLabel.setText("Loading Data");
tblData.initData(new Runnable() {
public void run() {
initTables();
}
});
}
private void initTables() {
waitLabel.setText("Loading Tables");
tblData.initTables(new Runnable() {
public void run() {
finishComponentsSetup();
}
});
}
private void finishComponentsSetup() {
waitLabel.setText("We are done");
}
}
TablesDataManager.java
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
import javax.swing.SwingWorker;
class TablesDataManager {
private final InitData initData = new InitData();
private final InitTables initTables = new InitTables();
void initData(final Runnable runAfterInit) {
launchWorker(initData, runAfterInit);
}
void initTables(final Runnable runAfterInit) {
launchWorker(initTables, runAfterInit);
}
private void launchWorker(final SimpleSwingWorker worker, final Runnable runAfterWorkerDone) {
worker.addPropertyChangeListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
if (evt.getPropertyName().equals("progress")) {
if (worker.getProgress() == 100) { //update finished
runAfterWorkerDone.run();
}
}
}
});
worker.execute();
}
private class InitData extends SimpleSwingWorker {
@Override
protected Void doInBackground() throws Exception {
//do something in the background
//unfortunately there is a connection problem
throw new IOException("Can't connect to database...");
}
}
private class InitTables extends SimpleSwingWorker {
@Override
protected Void doInBackground() throws Exception {
//do something else in the background
return null;
}
}
private abstract class SimpleSwingWorker extends SwingWorker<Void, Void> {
@Override
protected abstract Void doInBackground() throws Exception;
@Override
public void done() {
try {
get();
setProgress(100);
} catch (ExecutionException | InterruptedException e) {
System.out.println("Got that?");
//WHAT DO I DO WITH IT???
throw new RuntimeException(e);
}
}
}
}
答案 0 :(得分:8)
在GUI和工作中保留对工作者的引用添加try catch。在catch中为变量分配异常并为其添加一个getter。在你的GUI中,当你的工人完成后,只需检查工人是否有异常。
答案 1 :(得分:2)
我现在正在玩的替代方案(耦合稍低)是让工作人员触发propertyChange,异常为newValue
@Override
protected void done() {
try {
get();
} catch (Exception e) {
firePropertyChange("done-exception", null, e);
}
}