So I'm fairly new to Java Swing, and I stumbled upon a certain difficulty. I have a main Frame running (main part of the application that is visible throughout the app's execution) which has a button that once clicked, invokes a popup Frame (window) to collect user's information, and that frame has some Components. The problem being is that I don't really know the right approach to invoking the popup window and the main window freezing the execution and waiting until OK, or cancel button is clicked on the popup. Once this happens the main window code collects the returned values from the popup and resumes. I tried using synchronization to accomplish this, however the popup components don't even load, just the JFrame and JPanel (white background) and the popup freezes up on the wait() condition. I know that there is a way of doing it with JDialog and others, my main concern however, is to discover why the popup frame doesn't load the components and freezes up before the wait() condition. (when I get rid of wait() everything loads properly).
//in Main window Class:
frame.setEnabled(false);
Test test = getNewTest(); //should freeze on wait() in popup window
frame.setEnabled(true);
//in Popup Window Class
public Test getNewTest() {
addPanel.setVisible(true);
addFrame.setVisible(true);
synchronized(flag) {
try {
flag.wait();
} catch (InterruptedException e) {}
}
addPanel.setVisible(false);
addFrame.setVisible(false);
if(success)
return new Test(testName, date);
else return null;
}
//When OK or Cancel button clicked appropriate handler sets
//success value and invokes flag.notify();
Get all that synchronized and wait stuff out of your code. All that will do is freeze the Swing event thread, rendering your application useless.
You don't want to use a second JFrame, since an application typically has only one main window or JFrame, not multiple.
You want instead to use a modal dialog such as a JOptionPane (which can hold complex GUI's), or a modal JDialog (which also can hold a complex GUI). Be sure to associate the modal dialog with the parent JFrame. The Swing GUI library will then freeze the main window until the dialog has been dealt with, and the code from the main GUI will resume from the place the dialog was made visible after the dialog is no longer visible.
Related
I have a screen which has list. By right click, I can open a small pop up and add new records to the that list by choosing some record and clicking OK button from pop up.
OK button which is on pop up has an action listener like below:
okButton.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
setVisible(false);
}
});
And that is all the actionPerformed method does and I do not understand how this method is adding new record to the list on main window. There should be another part of code which is connected to this part but I do not know what is that. Do you have any idea what I do not see on that logic?
The ActionListener is not empty and in fact it is changing the state of the window that holds the JButton, making it no longer visible.
No one can say with 100% confidence what logic is being used here since you've yet to show enough code for that, but our guess is that this button is being held within a modal JDialog -- a window that freezes code flow in the calling code once the dialog window is visible, and (here's the key) that releases the block on code flow once this dialog is no longer visible. So in this situation, making the dialog no longer visible will allow the calling code, the code that initially told the dialog to display itself, to resume flow of its logic. Presumably in the subsequent code, it will query the dialog for data that was entered, and extract it, again the details of which are in code not yet shown to us.
In Swing for Java 1.5 I want to create a dialog, which allows the user to do other things in background. I want this dialog to have one button, with which you can close the dialog. If the user doesn't close the dialog within X seconds, it should close itself. In both cases a routine has to be done after the dialog has been closed.
I tried to use Swing Timer with a modal dialog and it works. But, as I noticed above, I need a non-modal dialog. When I set the modal-Property to false, the dialog disappears immediately.
Does someone know, why this happens?
JOptionPane pane = new JOptionPane (text, JOptionPane.WARNING_MESSAGE);
pane.setOptions(new String[]{"Close"});
final JDialog dialog = pane.createDialog(frame, title);
//dialog.setModal(false);
Timer timer = new Timer(time, new ActionListener() {
public void actionPerformed(ActionEvent e) {
dialog.setVisible(false);
}
});
timer.setRepeats(false);
timer.start();
dialog.setVisible(true);
//routine to do after the dialog disappears
for better help sooner post an SSCCE, there no code or descriptions about MultiThreading
don't create final JDialog dialog = pane.createDialog(frame, title); on runtime, create this JDialog one time and re_use that for another action, and / or by removing all childs from ContentPane
override proper event from WindowListener, there you can invoke your custom code before dipose(), setVisible() e.i.
(to point 2nd.) simply to override JDialog#setDefaultCloseOperation to HIDE_ON_CLOSE
all code that invoking a new Top-Level Container on runtime must be wrapped into invokeLater(), especially setVisible(true)
use Application Inactivity by #camickr
In this example, a modeless JDialog containing a direct JOptionPane counts down to zero before closing. A nearby JFrame containing a label remains responsive.
Addendum: As #mKorbel helpfully comments, your class can use a PropertyChangeListener to learn when the dialog's option pane closes. This is a convenient feature of JOptionPane, but you can add your own support, as shown here.
In the constructor of a JFrame Mygraph i invoke some work (retrieving remote data for a graph and painting it) to be done via invokeLater in the constructor:
SwingUtilities.invokeLater(doWorkRunnable);
This is all fine, however i sometimes want to display an dialog box at the end of the process to indicate that the requested set is truncated etc:
JOptionPane aMsg = Meldingen.Instance().getConclusie();
JDialog aDialog = aMsg.createDialog(null, "Meldingen");
//aDialog.setModal(false);
aDialog.setVisible(true);
When i click 'OK' on this dialog it also closes the parent frame. When i run it in a non-modal fashion it's ok as no other frames are closed. I cannot find which mechanism in the Swing Event universe causes the unrelated JFrame Mygraph to close. Can anyone point me in the right direction here?
I have an object which is invoked from the main GUI thread and shows a separate JFrame for a number of seconds and then disappear (with the use of a timer). Now I want to make the main GUI thread to wait until the pop-up JFrame window disappears. For example, on the main GUI code:
// initiate the object and show the pop-up JFrame
DisappearingJFrame djf = new DisappearingJFrame ();
djf.show ();
// now the main GUI thread should wait
// and after the pop-up JFrame disappears, the rest of the code is then executed
...
...
Any suggestion would be welcome. Thanks.
Don't use a separate JFrame for this is what modal dialogs were built for. Use either a JOptionPane or a modal JDialog.
I have an object which is invoked from the main GUI thread and shows a separate JFrame
If you want to show more than one TopLayoutContainer(s) maybe it is better to look for JDialog because with that you can play with ModalityType & toFront().
Isn't method show() deprecated and replaced with method JDialog.setVisible(boolean)?
Does exist in the JDialog class a way to prevent that a child window (JDialog) would be displayed more than once when the button from the main window (JFrame) used to open it, is pressed several times? Many thanks in advance!
Yes, and you don't need to make the box modal to do it (although making it modal would be the easiest way).
Simply do something like the following
In your member delcarations:
private final MyDialog dialog = new MyDialog();
In your code:
private void showDialog() {
dialog.setVisible(true);
dialog.requestFocus(); // May be needed to bring window to front
}
This will ensure that you only instantiate the box once. Simply call showDialog() whenever the button is pressed.
Another way that I've done in the past with Swing is that when the button is pressed the first thing I do is disable the button. Then I use the observable pattern to look at the child window and re-enable the button when the child window is closed. That way if it takes a while to display the child window for some reason the user can't click on it multiple times and mess things up.
You could make the JDialog modal, then the parent window would not react until it is closed.
Or you could initialize the JDialog before, and just make it visible when your button is pressed. Making it visible twice will not display it twice.