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.
Related
I'm new to Java and Swing. I created a jframe and I added a menubar and MenuItem in it.
On clicking a menu item, a jdialog should open. Now the jdialog has a jtextfield in it and a jlabel. Now the problem for me is 'when dialog is opened for first time, the textfield is empty and thats correct. Now i close the jdialog and i open it again but now instead of getting an empty textfield in jdialog, i get the data entered previously' which is not what should happen as the jdialogs 'default close operation' property is set to 'dispose'. but that is not happening for me...
I dont know what i'm doing wrong. I have never tried applet/swing before in any other way (consider this as my first demo learning programme)
Second Image here
The JTextField is retaining it's value because it isn't being affected by the JDialog closing, instead it is being hidden as it's parent (the JDialog) is invisible
Setting the dialog to dispose isn't re-initialising the child components, so they keep their values. Some additional information on this behaviour is available here:
JDialog setVisible(false) vs dispose()
JDialog
One way you can prevent / control this is by "informing" the dialog to wipe the textfield as it is closing by adding a WindowEvent and providing the necessary functionality in the windowClosing() method
Netbeans gui-builder will generate this for you with the following:
Right click Dialog
Events
Window
WindowClosing
Providing:
private void jDialog1WindowClosing(java.awt.event.WindowEvent evt) {
// TODO add your handling code here:
}
In which you can add: textfield.setText(""); to clear the textfield
Another approach is to create your own dialog and setting up the components in the constructor. As creating a new instance will contain the components with their default values, effectively resetting it
I have multiple JDialogs in my application stored in a map. These JDialogs are all have
setModel(false);
When these dialogs are out of focus and I want to bring a specific JDialog toFront all JDialogs come toFront. I want the specific Jdialog to come to front and want the other JDialogs to remain in back.
HashMap<String, JDialog> jDialogMap = getJDialogMap();
String key = "jd1";
JDialog specificJDialog= jDialogMap.get(key);
if (specificJDialog== null){
specificJDialog= new JDialog();
specificJDialog.setModel(false);
specificJDialog.setVisible(true);
jDialogMap.put("jd2", specificJDialog);
} else {
specificJDialog.toFront();
return;
}
This code brings all the JDialogs toFront having the specificJDialog on top of the stack.
getJDialogMap();
This Method only returns a HashMap nothing else.
use requiredDialogObject.requestFocusInWindow();
whenever u need focus on the specific dialog
I found a solution to my problem I think it is worth sharing it.
Solution: Creating multiple JDilogs in an application with default constructor i.e. new JDialog() will result in a shared frame as the parent of each JDialog which will cause these kind of problems. So I used the overloaded constructor new JDialog(new JFrame()) to have separate parent for each JDialog and that solved my problem.
Had a similar issue. After opening the JDialog my main application window just requested the focus again, moving the JDialog window to the background, which was annoying. I experimented with modal() and toFront() methods, which both didn't work out for me, since modal() just prevented user interaction completely (outside of that JDialog) and toFront() also has effect on windows outside my application (by using it inside of a timer method, see below).
To keep the window in front of the main application I used a timer method, which was fired every 300 ms and just keeps requesting the focus by using the requestFocus() method.
import javax.swing.Timer;
Timer timer = new Timer(300, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
requestFocus();
}
});
timer.start();
I've got a JDialog that's created and set to visible whenever the button is clicked.
My problem is that the button keeps the focus and doesn't give it to the JDialog.
Is this a normal behaviour or there's something wrong going on ?
JDialogs aren't modal (are "modeless") by default:
Creates a modeless dialog without a title and without a specified Frame owner.
Try constructing it as:
new JDialog(owner, title, ModalityType.APPLICATION_MODAL);
(Or the equivalent super() call if you're subclassing JDialog. Or whichever modality type you want.)
Try using dialog.requestFocus() if dialog is the newly created JDialog.
See requestFocus() or requestFocusInWindow() for more information.
I'm using JOptionPane.showOptionDialog to show a JDialog. I would like to know how:
set the dimension of the dialog (for now I'm using setPreferredSize() method on the given panel but I know that such method shouldn't be used).
make the showed dialog resizable.
My code looks like:
JPanel panel; //my JPanel built with dialog contents
int ret = JOptionPane.showOptionDialog(myFrame,
panel,
"titel",
JOptionPane.YES_NO_OPTION,
JOptionPane.PLAIN_MESSAGE,
null,
options,
options[1]);
I know that I could obtain the desired result building a JDialog this way:
JDialog dialog = new JDialog(panel);
dialog.setResizable(true);
dialog.setSize(800,600);
dialog.setVisible(true);
The problem with the last solution is that I can't get the return value.
EDIT:
in response to #camickr observations:
Why do you need to set the preferred size? If you build the panel
properly is should be displayed at its preferred size.
I'm not sure of having fully understood Swing on this point. The problem is, for example, that I'm displaying through a JDialog a ChartPanel built with JFreeChart. Now, I suppose that panel has it's own preferred size, but I want to see it bigger. How can I do that without explicitly use setPreferredSize()?
Read the JOptionPane API. Search for "Direct Use". It shows you how to
directly access the dialog used by the option pane and you can
I read it but I can't find the right method to understand which button (Ok or Cancel) has been pressed on the JDialog.
This hack using a HierarchyListener to get access to the JOptionPane's also works:
http://blogs.oracle.com/scblog/entry/tip_making_joptionpane_dialog_resizable
// TIP: Make the JOptionPane resizable using the HierarchyListener
pane.addHierarchyListener(new HierarchyListener() {
public void hierarchyChanged(HierarchyEvent e) {
Window window = SwingUtilities.getWindowAncestor(pane);
if (window instanceof Dialog) {
Dialog dialog = (Dialog)window;
if (!dialog.isResizable()) {
dialog.setResizable(true);
}
}
}
});
Why do you need to set the preferred size? If you build the panel properly is should be displayed at its preferred size.
Read the JOptionPane API. Search for "Direct Use". It shows you how to directly access the dialog used by the option pane and you can
With you second approach why are you setting the size? Again just pack() the dialog and it will be displayed at the panels preferred size.
What do you mean you can't get the return value? You have access to any method of your custom panel. So you can just invoke the getXXX() method when you receive control again. Just make sure the dialog is modal and the code after the setVisible(true) will block until the dialog is closed.
If you want to go the second way completely, you have to create and position your own "YES" and "NO" buttons somewhere (since a raw JDialog is just an empty modable frame). Therefore, you need to attach a MouseListener to both buttons and handle click events. On a click, you will know what button was pressed, and you'll just have to call dispose() on the dialog to close it.
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.