2012-02-29 7 views
3

メインクラスがあり、自分のGUIを処理し、独自のクラスTablesDataManagerに入れられたいくつかのSwingWorkers(DBおよびその他のデータソースへの呼び出し)を呼び出します。私の問題は、スイングワーカーのうちの1人がdone90メソッド(つまりEDT)内で例外をスローすると、何とかメインクラスでキャッチしてそれに応じて行動できるようにすることです(下のSSCCEでshowErrorAndExitを呼び出します)。異なるクラスにあるSwingWorkerによってキャッチ例外がスローされました

アイデアを歓迎します。

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

などの例外を除いて労働者の火のpropertyChangeをさせることです(HTTP [何とか私はこの質問を無視]:// stackoverflowの.COM /質問/ 7053865 /カント取得-は、ArrayIndexOutOfBoundsException-から未来-と-SwingWorkerの-IF-threa)、スレッドに名前を付ける、命名、命名は、例外の依存がそうでなければ、あなたが参照を失ったことができます入力し、なるほど私はここで答えを – mKorbel

+0

使用反対の意見しました[Executor](http://stackoverflow.com/a/6174462/714968)concurntly running threadの数が限られています – mKorbel

+0

@mKorbelはリンクをありがとうございます - 私は一見します。 – assylias

答えて

8

あなたのGUIで、あなたworkesであなたの従業員への参照を保持は、tryキャッチを追加します。 catchで例外に変数を代入し、ゲッターを追加します。あなたのGUIでは、あなたのワーカーが完了したら、ワーカーに例外があるかどうかをチェックするだけです。私は、最近で遊んだ

+0

それはトリックです!どうもありがとう。 – assylias

2

代替(やや低いカップリングとは)newValueに

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

私はそれを試みたが、例外が実際に発生したときに変更を正しくキャッチする方法を見つけることができなかったことを知っている。私はもう一度見てみましょう。ありがとう。 – assylias

+0

ええと...あなたはPropertyChangeListenerに解雇されなかったのですか?もしそうなら、私はあなたの見返りの結果に再び興味があります。私は何かを見落としているかもしれません:-) – kleopatra

+0

ギョームがシンプルな彼のソリューションを提案したので、私はそれに多くの時間を費やしませんでした効率的です。 – assylias

関連する問題