Use invokeLater to show dialogs one by one - java

In 2 different action listeners, a dialog will be shown when some conditions are met.
If both of the action listeners need to show dialog, 2 dialogs will be shown at the same time. But I want them to be shown one by one.
Simplified code:
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JOptionPane.showMessageDialog(getTopLevelAncestor(), "dialog 1");
}
});
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JOptionPane.showMessageDialog(getTopLevelAncestor(), "dialog 2");
}
});
Those 2 "SwingUtilities.invokeLater" invocations are in different classes.

Make a class that keeps track about that; this class would contain a queue of dialogs to display; whenever a dialog is closed, the first one of the queue is shown and removed from the queue. When another class needs to show a dialog, it's immediately shown if the queue is empty, or inserted into the queue else.

This is related to the modality of dialogs. There is quite useful article about this topic http://java.sun.com/developer/technicalArticles/J2SE/Desktop/javase6/modality/. Dialogs have different modality types with different priorities. You can solve your problem by creating the second dialog with lower priority:
JOptionPane pane = new JOptionPane("dialog 2", JOptionPane.INFORMATION_MESSAGE);
JDialog dialog = pane.createDialog("Message");
dialog.setModalityType(Dialog.ModalityType.DOCUMENT_MODAL);
dialog.setVisible(true);
Hopefully this helps.

You need invokeAndWait(), this method waits until the Runnable has been finished.
Or in your situation, when the first dialog has been closed.

Related

Is there a way to cancel the popup menu within popupMenuWillBecomeVisible()?

In my java app, I've been using the popupMenuWillBecomeVisible() event to decide on which menu-items within my JPopupMenu will be enabled/disabled/visible/hidden, etc.
I've used the JPopupMenu as a right-click context menu of a JList, and I decide on the state of the menu-items depending on which item in the list was right-clicked.
This is all working fine. The only gotchya I have is for the case where the list is empty, or the right-click was triggered when no item was selected.
For this case, I was hoping that I could cancel the appearance of the JPopupMenu from within the popupMenuWillBecomeVisible() event, as that's where I currently perform my existing tests.
Is there a way to do this? Perhaps some sort of way to 'consume' the event?
If not, perhaps my only other option will be to try alternatives, such as moving the testing logic somewhere else, prior to the right-click.
Still, my preference at this stage was to keep the logic within popupMenuWillBecomeVisible(), unless that proves to be impossible.
Anyone got any ideas?
SwingUtilities.InvokeLater will wait until all AWT operations are finished before starting the runnable, which means this runnable will be called after the popupMenuWillBecomeVisible event is finished and the popup menu is visible or in queue to be painted.
final JPopupMenu popupMenu = new JPopupMenu();
popupMenu.addPopupMenuListener(new PopupMenuListener() {
#Override
public void popupMenuWillBecomeVisible(final PopupMenuEvent e) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
((JPopupMenu)e.getSource()).setVisible(false);
}
});
}

Progress bar for loading out another JFrame class

I have 2 JFrame: NewJFrame and NewJFrame1. NewJFrame has a progress bar and a button. the button is used to call up NewJFrame1. When the button is clicked it should trigger the progress bar to run until NewJFrame1 pop up. However, how do I make use of the swing worker and let the progress to run until NewJFrame1 actually competely loaded all of its component?
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
SwingUtilities.invokeLater(new Runnable() {
int i = 0;
public void run() {
jProgressBar1.setValue(i++);
new NewJFrame1().setVisible(true);
}
});
}
Let your top-level container have a SwingWorker that loads it's content, as shown here, and a PropertyChangeListener, as shown here. When doInBackground() calls setProgress(), the listener will see the event.
Addendum: How do we know how much time left for the GUI to be completely loaded? …in examples, the progress bar is run with random number as simulated latency.
Correct; the simulated latency represents the granularity of your loading. Displaying the fraction of total bytes loaded would be ideal, but you may have to settle for a coarser frequency. Note that models may be constructed in the background, before any components are listening. GUI components should be constructed and manipulated only on the EDT, possibly in the worker's process() implementation.

Automatically close non-modal dialogs after specified time in swing 1.5

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.

Closing JOptionPane.ShowInternalOptionDialog programmatically

My current design is like this:
I have an outer frame that displays main app. When user clicks a button on the main app, a pop-up Window should be launched. I am using JOptionPane.showInternalOptionDialog and passing button objects as options. When user clicks one of these button, it should run certain commands and then close the window. I was not able to close the Frame that shows the pop-up.
I found a similar question in this forum, that suggests the following workaround.
Closing a dialog created by JOptionPane.showOptionDialog()
But the above workaround closes my complete gui. I just want to close the JOptionPane popup.
Thanks in advance.
try
JOptionPane.getRootFrame().dispose();
in a event
A couple of solutions:
Create a JOptionPane directly instead of using the showX() methods. This will allow you to have a reference to the dialog that you can pass to your button to allow it to call the dispose method().
Create your own dialog instead of using JOptionPane. This would be my preferred option, seeing that you are starting to get away from a simple dialog.
I had the same problem. I solve it using a thread that close my JOptionPane after X milliseconds.
import javax.swing.JOptionPane;
public class JOptionPaneExample {
public static void main(String[] args) {
final JOptionPane pane =new JOptionPane();
Thread t1 = new Thread(new Runnable() {
public void run() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
pane.getRootFrame().dispose();
}
});
t1.start();
pane.showMessageDialog(null, "I will close after 3000 milli's", "Programmatic Auto-close JOptionPane", JOptionPane.INFORMATION_MESSAGE);
System.exit(0);
}
}
By default, clicking a button in a JOptionPane will close the dialog. If yours doesn't, it's because you are using actual components rather than strings or other objects, and it is calling your buttons' custom event handlers instead of its own.
I would recommend you take a different approach, using strings instead of buttons. Use an array of buttons as your input values, and when the call to showInternalOptionDialog returns, you can check the int index to find out what was pressed, and then switch on it in your code. This way, you don't have to touch the JOptionPane at all and it will close by itself.

Programmatic close of JFrame

What's the programmatic equivalent of clicking the close (x) button in the upper right corner of a JFrame?
There's the dispose() method but that's not the same thing, since a JFrame can be set to do several different things upon closing (not to mention if there's a WindowListener involved)
You tell the component to dispatch an event. In this case, you want it do dispatch a Window Closing event.
private void exit() {
this.dispatchEvent(new WindowEvent(this, WindowEvent.WINDOW_CLOSING));
}
When you hit the x on a JFrame, the system can be set to do various things. The default is that the window is simply hidden with setVisible(false) I believe.
You can set a frame to do different things on close--you can have it dispose, hide or call code based on setDefaultCloseOperation. Here are the options:
DO_NOTHING_ON_CLOSE: Don't do anything; require the program to handle the operation in the windowClosing method of a registered WindowListener object.
HIDE_ON_CLOSE: Automatically hide the frame after invoking any registered WindowListener objects.
DISPOSE_ON_CLOSE: Automatically hide and dispose the frame after invoking any registered WindowListener objects.
EXIT_ON_CLOSE: Exit the application using the System exit method. Use this only in applications.
But I think what you are after is setVisible(false).
You have to insert the call into the AWT message queue so all the timing happens correctly, otherwise it will not dispatch the correct event sequence, especially in a multi-threaded program.
public void closeWindow()
{
if(awtWindow_ != null) {
EventQueue.invokeLater(new Runnable() {
public void run() {
awtWindow_.dispatchEvent(new WindowEvent(awtWindow_, WindowEvent.WINDOW_CLOSING));
}
});
}
}

Categories

Resources