setvisible method in java swing hangs system
Solution 1
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.
Solution 2
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.
Solution 3
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.
Adith
Updated on June 20, 2022Comments
-
Adith almost 2 years
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();
-
Adith over 13 yearsThanks for the quick responses! I am still a bit shaky on these kind of aspects to gui programming but I get it for the most part now...
-
Jiri Patera over 13 yearsUnderstanding to how the Swing Event-Dispatch Thread works and how to use it in the right way was the hardest part of the Swing GUI for me. Take your time and get it right, it will save you a lot of trouble later on.
-
Ryan about 10 yearsThe done method is executed on the Event Dispatch Thread so I don't think you need to use SwingUtilities.invokeLater in that method. See docs.oracle.com/javase/6/docs/api/javax/swing/…
-
Ryan about 10 yearsAlso this answer has a race condition: it is possible for the done method to be called and the dialog destroyed before the dialog is set to visible.
-
Jiri Patera about 10 yearsI may be missing something, I was focusing mainly only on the OP's problem, but from my point of view the race condition, you are mentioning, is not possible here. You set the dialog visible via the code here BEFORE you call the
done()
method. The reason is that both the actions are done in a serial way in the Swing Event-Dispatch thread. The use of theSwingUtilities.invokeLater(Runnable)
method posts the actions to the thread in a synchronized way, i.e. no race condition you described is possible here.