java swing中的setvisible方法挂起系统
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4413310/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
setvisible method in java swing hangs system
提问by Adith
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:
我有我目前正在开发的银行 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();
回答by Jiri Patera
First, it is recommended to do all the GUI updates in the Swing Event-Dispatch thread, i.e. using the SwingUtilites
class.
首先,建议在 Swing Event-Dispatch 线程中完成所有 GUI 更新,即使用SwingUtilites
类。
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).
其次,您JDialog
是模态的,因此会阻塞setVisible(true)
调用该方法的线程(在您的情况下是主线程,在以下情况下是 Swing 事件调度线程)。
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.
希望这可以帮助。
回答by camickr
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.
在 setVisible 之后添加 System.out.println(...) 语句,您将看到它永远不会执行。
回答by ColinD
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 neverbe called except on the Swing event dispatch thread. You're calling it from the doInBackground
method of SwingWorker
, which runs on a background thread.
setVisible
是一种影响 GUI 的方法,导致显示某些内容(并且,在像您这样的模态对话框的情况下,阻塞直到对话框关闭)。除了在 Swing 事件分派线程上之外,永远不应调用它(与修改可见 UI 的所有其他内容一样)。您从 的doInBackground
方法中调用它,该方法SwingWorker
在后台线程上运行。
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 afterstarting the worker.
你需要做的,解决这个问题是什么使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
You need to do it in this order because otherwise the modal dialog will block you from starting the worker.
您需要按此顺序执行此操作,否则模态对话框将阻止您启动工作程序。
回答by Uhlen
camickr gives you correct answer. I want to add that you may notmodify 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.
camickr 给你正确答案。我想补充一点,您不能在事件调度线程之外修改 UI (正如您在 中所做的那样#doInBackground
),Swing 是单线程的,因此违反此规则可能会导致您的 UI 中出现非常棘手的错误和奇怪的事情。