java swing中的setvisible方法挂起系统

发布于 2024-10-06 22:49:03 字数 1220 浏览 0 评论 0原文

我目前正在开发银行 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();

I have banking gui application that I am currently working on and there seems to be a problem with the setvisible method for my jdialog. After the user has withdrawn a valid amount I pop up a simple dialog that says "transaction in progress". In my dobackground method i keep polling to check if the transaction has been received. I tried using swingworker and I don't understand why it's not working. If i remove the setvisible call it works fine, so why does setvisible cause the system to hang? Here is the code that is inside my 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();

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

囚你心 2024-10-13 22:49:03

首先,建议在 Swing Event-Dispatch 线程中执行所有 GUI 更新,即使用 SwingUtilites 类。

其次,您的 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);
  }
});

希望这会有所帮助。

First, it is recommended to do all the GUI updates in the Swing Event-Dispatch thread, i.e. using the SwingUtilites class.

Second, your JDialog is modal and so blocks the thread in which the setVisible(true) method is called (in your case the Main thread, in the following case the Swing Event-Dispatch Thread).

I do not say the following code is perfect, but it should put you on the track...


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

Hope this helps.

天煞孤星 2024-10-13 22:49:03

您正在显示一个模式对话框,因此在对话框关闭之前后台代码无法执行。

在 setVisible 之后添加 System.out.println(...) 语句,您将看到它永远不会执行。

You are displaying a modal dialog so the background code can't execute until the dialog is closed.

Add a System.out.println(...) statement after the setVisible and you will see it never executes.

心舞飞扬 2024-10-13 22:49:03

setVisible 是一种影响 GUI 的方法,导致显示某些内容(并且,在像您这样的模态对话框的情况下,会阻塞直到对话框关闭)。除了在 Swing 事件调度线程上之外,决不应该调用它(与修改可见 UI 的其他所有内容一样)。您从 SwingWorkerdoInBackground 方法调用它,该方法在后台线程上运行。

要解决此问题,您需要做的是将 waitForClose 对话框设置为在 SwingWorker< 上调用 execute 之前创建的 final 变量。 /code>,然后在启动工作线程后立即调用 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

您需要按此顺序执行此操作,否则模式对话框将阻止您启动工作程序。

setVisible is a method that affects the GUI, causing something to be shown (and, in the case of a modal dialog like yours, block until the dialog is closed). It (like everything else that modifies the visible UI) should never be called except on the Swing event dispatch thread. You're calling it from the doInBackground method of SwingWorker, which runs on a background thread.

What you need to do to fix this is make the waitForClose dialog a final variable that you create before calling execute on the SwingWorker and then call setVisible on immediately after starting the worker.

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

You need to do it in this order because otherwise the modal dialog will block you from starting the worker.

一花一树开 2024-10-13 22:49:03

camickr 给你正确的答案。我想补充一点,您不得事件调度线程之外修改 UI(如您在 #doInBackground 中所做的那样),Swing 是单线程的因此,违反此规则可能会导致用户界面中出现非常棘手的错误和奇怪的事情。

camickr gives you correct answer. I want to add that you may not modify the UI outside the Event Dispatch Thread (as you do in #doInBackground), Swing is single threaded so violating this rule could lead to very tricky bugs and strange things in your UI.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文