9

我有我目前正在处理的银行 gui 应用程序,我的 jdialog 的 setvisible 方法似乎有问题。在用户提取有效金额后,我会弹出一个简单的对话框,上面写着“正在进行交易”。在我的 dobackground 方法中,我不断轮询以检查是否已收到交易。我尝试使用 swingworker,但我不明白为什么它不起作用。如果我删除 setvisible 调用它工作正常,那么为什么 setvisible 会导致系统挂起?这是我的 jbutton mouselistener 中的代码:

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 线程中进行所有的 GUI 更新,即使用SwingUtilites类。

其次,您JDialog是模态的,因此阻塞了调用该setVisible(true)方法的线程(在您的情况下是主线程,在以下情况下是 Swing Event-Dispatch 线程)。

我并不是说下面的代码是完美的,但它应该让你走上正轨......


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您在调用之前创建的变量,execute然后SwingWorker在启动工作程序setVisible立即调用。

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 给你正确的答案。我想补充一点,您不能在Event Dispatch Thread之外修改 UI (就像您在 中所做的那样#doInBackground),Swing 是单线程的,因此违反此规则可能会导致您的 UI 中出现非常棘手的错误和奇怪的事情。

于 2010-12-10T21:21:51.263 回答