Исключение Catch, выданное SwingWorker, расположенным в другом классе - PullRequest
3 голосов
/ 29 февраля 2012

У меня есть основной класс Gui, который обрабатывает мой графический интерфейс и вызывает несколько SwingWorkers (обращений к БД и другим источникам данных), которые были помещены в их собственный класс TablesDataManager.Моя проблема заключается в том, что когда один из тех, кто работает в Swing, генерирует исключение в своем методе done90 (т.е. в EDT), я хочу иметь возможность каким-то образом перехватить его в основном классе и действовать соответствующим образом (вызовите showErrorAndExit в моем SSCCE ниже).

Любые идеи приветствуются.

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);
            }
        }
    }
}

Ответы [ 2 ]

8 голосов
/ 29 февраля 2012

Сохраняйте ссылку на своих работников в своем графическом интерфейсе, а в своих работах добавляйте попытку.В улове присвойте исключение переменной и добавьте к ней геттер.В вашем графическом интерфейсе, когда ваш работник закончил, просто проверьте, есть ли исключение в работнике или нет.

2 голосов
/ 06 марта 2012

Альтернатива (с немного меньшей связью), с которой я сейчас играю, состоит в том, чтобы позволить работнику запустить свойствоChange с исключением как newValue

@Override
protected void done() {
    try {
        get();
    } catch (Exception e) {
        firePropertyChange("done-exception", null, e);
    }
}
...