9

現在取り組んでいるバンキングGUIアプリケーションがあり、jdialogのsetvisibleメソッドに問題があるようです。ユーザーが有効な金額を引き出した後、「トランザクションが進行中です」という簡単なダイアログが表示されます。私のdobackgroundメソッドでは、トランザクションが受信されたかどうかを確認するためにポーリングを続けます。私はswingworkerを使ってみましたが、なぜそれが機能しないのかわかりません。setvisible呼び出しを削除すると正常に機能しますが、なぜsetvisibleによってシステムがハングするのですか?これが私のjbuttonmouselistener内にあるコードです:

SwingWorker<String,Integer> worker = new SwingWorker<String,Integer>(){

  JDialog waitForTrans = new JDialog((JFrame)null,true);
  public String doInBackground() throws Exception {
     waitForTrans.add(new JLabel("Updating balance in system. Please Wait..."));
     waitForTrans.setMinimumSize(new Dimension(300,100));
     waitForTrans.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
     waitForTrans.setVisible(true);
     Bank.getInstance().sendTransaction(currentPin,"-"+withdraw);
     while(!Bank.getInstance().hasCompletedTransaction){

     }
     return null;

  }

  public void done(){
   try {
        this.get();
       } catch (InterruptedException e) {
        e.printStackTrace();
    } catch (ExecutionException e) {

        e.printStackTrace();
    }
    waitForTrans.setVisible(false);
    newField.setText(String.valueOf(Bank.getInstance().getAccountList().get(currentPin).getBalance()));
  }

 };
 worker.execute();
4

4 に答える 4

15

まず、Swing Event-Dispatchスレッドで、つまりSwingUtilitesクラスを使用して、すべてのGUI更新を実行することをお勧めします。

次に、JDialogはモーダルであるため、setVisible(true)メソッドが呼び出されるスレッド(この場合はメインスレッド、次の場合はSwingイベント-ディスパッチスレッド)をブロックします。

次のコードが完璧だとは言いませんが、それはあなたを軌道に乗せるはずです...


final JDialog waitForTrans = new JDialog((JFrame) null, true);

SwingWorker worker = new SwingWorker() {

  public String doInBackground() throws Exception {
    Thread.sleep(5000);
    return null;
  }

  public void done() {
    SwingUtilities.invokeLater(new Runnable() {
      public void run() {
        waitForTrans.setVisible(false);
        waitForTrans.dispose();
      }
    });
  }

};

worker.execute();
SwingUtilities.invokeLater(new Runnable() {
  public void run() {
    waitForTrans.add(new JLabel("Please Wait..."));
    waitForTrans.setMinimumSize(new Dimension(300, 100));
    waitForTrans.setVisible(true);
  }
});

お役に立てれば。

于 2010-12-10T21:41:41.633 に答える
6

モーダルダイアログを表示しているため、ダイアログを閉じるまでバックグラウンドコードを実行できません。

setVisibleの後にSystem.out.println(...)ステートメントを追加すると、実行されないことがわかります。

于 2010-12-10T21:11:37.550 に答える
2

setVisibleはGUIに影響を与えるメソッドであり、何かが表示されます(また、あなたのようなモーダルダイアログの場合は、ダイアログが閉じるまでブロックします)。Swingイベントディスパッチスレッドを除いて、(表示されているUIを変更する他のすべてのように)呼び出さないでください。バックグラウンドスレッドで実行されるのdoInBackgroundメソッドから呼び出しています。SwingWorker

これを修正するために必要なことは、waitForCloseダイアログを呼び出す前に作成する変数finalにし、ワーカーを起動た直後に呼び出すことです。executeSwingWorkersetVisible

final JDialog waitForTrans = ...
// set up the dialog here

SwingWorker<String, Integer> worker = new SwingWorker<String, Integer>() {
  ...
};
worker.execute(); // start the background process

waitForTrans.setVisible(true); // show the dialog

モーダルダイアログがワーカーの起動をブロックするため、この順序で実行する必要があります。

于 2010-12-10T21:24:42.573 に答える
0

camickrはあなたに正しい答えを与えます。イベントディスパッチスレッドの外部でUIを変更することはできません(のように)。Swingはシングルスレッドであるため、このルールに違反すると、UIに非常にトリッキーなバグや奇妙なことが発生する可能性があります。#doInBackground

于 2010-12-10T21:21:51.263 に答える