1

イベントディスパッチスレッドから呼び出され、完全に初期化されたUIコンポーネントを返す必要があるJavaライブラリでAPIを使用しています。次のようになります。

public JDialog createDialog();

ただし、データベースからロードした後にのみダイアログにデータを入力できます。これには10秒かかる場合があります。通常はバックグラウンドスレッドでこれを行いますが、このメソッドはEDTから呼び出され、ダイアログを返す必要があるため、機能しません。これはサードパーティのライブラリなので、メソッドを変更することはできませんが、EDTのブロックを回避するためにできることはありますか?

4

2 に答える 2

5

「初期化済み」と「実装済み」は必ずしも同じではありません。「初期化済み」は通常、オブジェクトが完全に構築されているが、データがない可能性があることを意味します。もちろん、「入力済み」とは、データが存在し、データ取得タスクが完了していることを意味します。そのため、サードパーティのライブラリに、データがまったくない完全に初期化された JDialog を与えることができます。

私がいつもこの問題を解決したいと思っている方法は、ビジー メッセージやプログレス バーなどを表示するカスタム JDialog を作成し、別のスレッドでデータを要求することです。データが返されたら、ビジー メッセージをデータに置き換えます (EDT で!)。バックグラウンド スレッドでリクエストを実行する方法については、SwingWorkers を使用することをお勧めします。メソッドでリクエストを処理し、メソッドで表示関連のタスクをSwingWorker処理するカスタム JDialog 内でプライベートを使用するのが好きです。このようにすると、表示関連のタスクは EDT でのみ発生し、データベース関連のタスクは EDT 以外でのみ発生するようになります。SwingWorkers を使用するための適切な入門書が必要な場合は、ワーカー スレッドに関する Sun のチュートリアルを参照してください。簡単な例は次のとおりです。doInBackground()done()

public class DBDIalog extends JDialog{
     private JLabel busyLabel = new JLabel("Fetching data from DataBase");
     
     public DBDialog(){
         //do your initialization stuff here
     }

     private class DBFetcher extends SwingWorker<Void,DBInfo>{
         
        @Override
        protected DBInfo doInBackground() throws Exception{
            return fetchDataFromDB(); //or whatever database call to make
        }

        @Override
        protected void done(){
           try{
               DBInfo info = get();
           //replace your busy label with your DBInfo
           }catch(InterruptedException e){
              //do appropriate thread interrupted stuff
           }catch(ExecutionException e){
              //do appropriate general error handling stuff 
           }

        }
     }
}

ただし、覚えておくべきことがいくつかあります。done()メソッドは抽象的ではないため、オーバーライドする必要はありません。ただし、そうする必要があります。実装が例外をスローした場合、オーバーライドされていdoInBackground()ない限り、その例外は飲み込まれます。また、 を使用しない限りdone()、内部から GUI を変更しないでください。これは、EDT とは異なるスレッドから実行され、バックグラウンド スレッドから GUI の変更を行うと、奇妙で​​説明のつかないバグが発生するからです。doInBackground()SwingUtilities.invokeLater(Runnable)doInBackground()

これはいつ使用する必要がありますか?他のプログラミング タスクとは異なり、何かの応答に時間がかかりすぎるポイントは、GUI でははるかに短くなります。私が通常目にする数値は約 250 ミリ秒です。タスクにそれよりも時間がかかる場合は、バックグラウンド スレッドにする必要があります。あなたの場合、10秒は間違いなくバックグラウンドスレッドにあるはずですが、それはすでに知っていました:)

編集:

あなたのコメントを見て、私の投稿のほとんどがかなり馬鹿げていることがわかりました。ただし、SwingWorker は引き続き使用できます。

SwingWorker にデータ取得を実行させ、done()メソッドでデータから JDialog を構築させ、そのダイアログをサードパーティ ライブラリに渡します。

于 2009-12-31T21:12:54.017 に答える
1

データなしでダイアログを作成し、タスクを開始してデータを入力します。

ユーザーエクスペリエンスの観点からは、開始から完了までに10秒かかるものはすべて問題になります。最終的な形でなくても、すぐに何かをすべきであることが最善です。必要に応じて、単に「読み込み中」というモーダルダイアログを表示できます。

于 2009-12-31T20:43:50.063 に答える