java swing中的setvisible方法挂起系统

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

SwingWorker worker = new SwingWorker(){ 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(); 

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

其次,你的JDialog是模态的,因此阻塞了调用setVisible(true)方法的线程(在你的情况下是主线程,在下面的例子中是Swing Event-Dispatch Thread)。

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

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

希望这可以帮助。

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

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

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

你需要做的就是使waitForClose对话框成为你在SwingWorker上调用execute之前创建的final变量,然后启动worker 之后立即调用setVisible

 final JDialog waitForTrans = ... // set up the dialog here SwingWorker worker = new SwingWorker() { ... }; worker.execute(); // start the background process waitForTrans.setVisible(true); // show the dialog 

您需要按此顺序执行此操作,否则modal dialog将阻止您启动工作程序。

camickr给你正确的答案。 我想补充一点,你可能不会修改Event Dispatch Thread之外的UI(正如你在#doInBackground所做的#doInBackground ),Swing是单线程的,所以违反这个规则可能会导致你的UI中出现非常棘手的错误和奇怪的事情。