This question already has an answer here:
Calling one JFrame from another using Timer without any buttons
(1 answer)
Closed 8 years ago.
Help needed for making a popup which automatically closes after a few seconds. JOptionpane messages usually needs an input to close, so is there any other way to handle auto-closing popup in java. Please help. Thanks in advance.
If the option pane can be modeless, this might be one way to do it:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.Timer;
public class AutoCloseJOption {
private static final int TIME_VISIBLE = 3000;
public static void main(String[] args) {
final JFrame frame1 = new JFrame("My App");
frame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame1.setSize(100, 100);
frame1.setLocation(100, 100);
JButton button = new JButton("My Button");
frame1.getContentPane().add(button);
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
JOptionPane pane = new JOptionPane("Message", JOptionPane.INFORMATION_MESSAGE);
JDialog dialog = pane.createDialog(null, "Title");
dialog.setModal(false);
dialog.setVisible(true);
new Timer(TIME_VISIBLE, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
dialog.setVisible(false);
}
}).start();
}
});
frame1.setVisible(true);
}
}
For this example, press the button and an option dialog will be visible for three seconds.
Related
I'm learning about threads and I've got a problem with it. I'm trying to make 2 frames, one is a main frame and another will be shown later after clicking on a button. I want to stop the main frame while the new frame is running. Can you guys help me with a very simple example for this? (And the new frame will be closed after clicking on a button too). Just 2 frames with a button on each are enough. Much appreciated!
You should avoid the use of multiple JFrames, use modal dialogs instead. JOptionPane offers a ton of good, easy & flexible methods to do so.
Here's an example. When you click the button the dialog will appear on top of the JFrame. The main JFrame won't be clickable anymore, since JOptionPane.showMessageDialog() produces a modal window.
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
public class Example {
public Example() {
JFrame frame = new JFrame();
JButton button = new JButton("Click me");
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
JOptionPane.showMessageDialog(frame, "I'm a dialog!");
}
});
frame.getContentPane().setLayout(new FlowLayout());
frame.getContentPane().add(button);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new Example();
}
});
}
}
Output:
I am displaying a JOptionPane suppose A on a button click from JFrame, and again displaying another JOptionPane suppose B on a button click from JOptionPane A, and I have a button on JOptionPane B suppoce button1, on the click event of button1, I am using code JOptionPane.getRootFrame().dispose() for closing the JOptionPane B, but it closes both A and B, please help me how can close only B but not A.
here is my sample code
i want second JOptionPane must be open
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
public class SampleCode extends JFrame {
public SampleCode() {
setSize(new Dimension(500, 500));
setLocation(450, 150);
but1 = new JButton("Click me");
add(but1);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
but1.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
but1Function();
}
});
}
public static void main(String args[]) {
new SampleCode();
}
void but1Function() {
JPanel panel1 = new JPanel();
JButton but2 = new JButton("Open new dialog");
panel1.add(but2);
but2.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
JPanel pan2 = new JPanel();
JButton but3 = new JButton("click me to close");
pan2.add(but3);
but3.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
JOptionPane.getRootFrame().dispose();
}
});
JOptionPane.showMessageDialog(null, pan2);
}
});
JOptionPane jp = new JOptionPane(panel1, JOptionPane.CLOSED_OPTION,
JOptionPane.DEFAULT_OPTION, null, new Object[] {}, null);
JDialog dialog = jp.createDialog(null, "This one must be remain open");
dialog.setLocation(500, 200);
dialog.setSize(new Dimension(345, 200));
dialog.setVisible(true);
}
JButton but1;
}
You don't want to get the root frame nor dispose of it. You want to get the window that is displaying the JOptionPane, a Window that should be a modal JDialog. So instead, use SwingUtilities.getWindowAncestor(someComponentInJOptionPane), and call dispose() on that Window if you want to programmatically dispose of your JOPtionPane.
import java.awt.Component;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class OptionPaneFun {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#SuppressWarnings("serial")
public void run() {
final JPanel panel1 = new JPanel();
panel1.add(new JButton(new AbstractAction("Show new option pane") {
{
putValue(MNEMONIC_KEY, KeyEvent.VK_S);
}
#Override
public void actionPerformed(ActionEvent e1) {
final JPanel panel2= new JPanel();
panel2.add(new JButton(new AbstractAction("Dispose of this option pane") {
{
putValue(MNEMONIC_KEY, KeyEvent.VK_D);
}
#Override
public void actionPerformed(ActionEvent e2) {
Component comp = (Component) e2.getSource();
Window win = SwingUtilities.getWindowAncestor(comp);
if (win != null) {
win.dispose();
}
}
}));
JOptionPane.showMessageDialog(panel1, panel2);
}
}));
JOptionPane.showMessageDialog(null, panel1);
}
});
}
}
The static method "getRootFrame()" returns your root frame which is the only one and it's the same for both your components (A and B). What you need to do - you have to put two frames in your root frame (call them frameA and frameB) and put paneA to frameA and paneB to frameB. Instead of calling this static method just invoke frameB.dispose() on reference frameB which you already have.
Try to add
panel.validiate();
After the dispose command. I had the same problem once and it helped a lot when I used this trick.
Basically when you add this command, it is telling the frame to validate or actually do it.
Read the oracle docs for more info.
I am facing issues when I set my first JDialog modal and the second one non-modal.
This is the functionality I am trying to implement:
On click of "Test the dialog!" button, a JDialog with name Custom Dialog
Main will open.
If click "yes" option in Custom Dialog Main, another
JDialog named Custom Dialog Search will open.
If click "yes" option in Custom Dialog Search, then
Custom Dialog Main should come front.
And I should be able to select any JDialog. For example if I select
Custom Dialog Search, the other dialog should go
back and vice versa.
Problem I am facing is when I click "yes" in Custom Dialog Main, then Custom Dialog Search is displayed behind the main dialog.
This is happening because I am setting Custom Dialog Search non-modal.
If I this dialog modal it is displayed correctly but after I click "yes" Custom Dialog Main doesn't come front.
I even tried to set CustomDialogSearch's parent to be CustomDialog the behaviour still not correct.
Below is the example code I am testing.
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JButton;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.ActionEvent;
import java.awt.Dimension;
public class TestTheDialog implements ActionListener {
JFrame mainFrame = null;
JButton myButton = null;
public TestTheDialog() {
mainFrame = new JFrame("TestTheDialog Tester");
mainFrame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {System.exit(0);}
});
myButton = new JButton("Test the dialog!");
myButton.addActionListener(this);
mainFrame.setLocationRelativeTo(null);
mainFrame.getContentPane().add(myButton);
mainFrame.pack();
mainFrame.setVisible(true);
}
public void actionPerformed(ActionEvent e) {
if(myButton == e.getSource()) {
System.err.println("Opening dialog.");
CustomDialog myDialog = new CustomDialog(mainFrame, true, "Custom Dialog Main?");
System.err.println("After opening dialog.");
if(myDialog.getAnswer()) {
System.err.println("The answer stored in CustomDialog is 'true' (i.e. user clicked yes button.)");
}
else {
System.err.println("The answer stored in CustomDialog is 'false' (i.e. user clicked no button.)");
}
}
}
public static void main(String argv[]) {
TestTheDialog tester = new TestTheDialog();
}
}
import javax.swing.JDialog;
import java.awt.event.ActionListener;
import javax.swing.JPanel;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JButton;
import java.awt.event.ActionEvent;
public class CustomDialog extends JDialog implements ActionListener {
private JPanel myPanel = null;
private JButton yesButton = null;
private JButton noButton = null;
private boolean answer = false;
private JFrame parentFrame;
public boolean getAnswer() { return answer; }
public CustomDialog(JFrame frame, boolean modal, String myMessage) {
super(frame, modal);
parentFrame = frame;
myPanel = new JPanel();
getContentPane().add(myPanel);
myPanel.add(new JLabel(myMessage));
yesButton = new JButton("Yes");
yesButton.addActionListener(this);
myPanel.add(yesButton);
noButton = new JButton("No");
noButton.addActionListener(this);
myPanel.add(noButton);
pack();
setLocationRelativeTo(frame);
setVisible(true);
}
public void actionPerformed(ActionEvent e) {
if(yesButton == e.getSource()) {
CustomDialogSearch myDialog = new CustomDialogSearch(parentFrame, false, "CustomDialog Search?");
System.err.println("User chose yes.");
answer = true;
myDialog.getAnswer();
System.out.println("myDialog.getAnswer()="+myDialog.getAnswer());
myDialog.show();
if(myDialog.getAnswer()==true)
{
System.out.println("tofront");
this.toFront();
}
//setVisible(false);
}
else if(noButton == e.getSource()) {
System.err.println("User chose no.");
answer = false;
setVisible(false);
}
}
}
import javax.swing.JDialog;
import java.awt.event.ActionListener;
import javax.swing.JPanel;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JButton;
import java.awt.event.ActionEvent;
public class CustomDialogSearch extends JDialog implements ActionListener {
private JPanel myPanel = null;
private JButton yesButton = null;
private JButton noButton = null;
private boolean answer = false;
public boolean getAnswer() { return answer; }
public CustomDialogSearch(JFrame frame, boolean modal, String myMessage) {
super(frame, modal);
myPanel = new JPanel();
getContentPane().add(myPanel);
myPanel.add(new JLabel(myMessage));
yesButton = new JButton("Yes");
yesButton.addActionListener(this);
myPanel.add(yesButton);
noButton = new JButton("No");
noButton.addActionListener(this);
myPanel.add(noButton);
pack();
setLocationRelativeTo(frame);
setVisible(true);
}
public void actionPerformed(ActionEvent e) {
if(yesButton == e.getSource()) {
System.err.println("Search User chose yes.");
answer = true;
//setVisible(false);
}
else if(noButton == e.getSource()) {
System.err.println("Search User chose no.");
answer = false;
setVisible(false);
}
}
}
I even tried to set CustomDialogSearch's parent to be CustomDialog the
behaviour still not correct.
I think you're in the right track here but you need to play with dialogs modality type. For instance:
Set the modality type of Custom Dialog Main ("parent" dialog) as Dialog.ModalityType.APPLICATION_MODAL. By doing this when this dialog is visible it will block all windows except its children.
Set the modality type of Custom Dialog Search ("child" dialog) as Dialog.ModalityType.MODELESS. This way it won't block any other window and you can go from the child to the parent and vice versa.
For a better understanding take a look to How to Use Modality in Dialogs article.
Example
Here is a code example about using modality as I've suggested above:
import java.awt.Dialog;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
public class Demo {
private void createAndShowGUI() {
JButton button = new JButton("Create Parent modal dialog");
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
JButton button = (JButton)e.getSource();
JFrame owner = (JFrame)SwingUtilities.windowForComponent(button);
Demo.this.createAndShowParentDialog(owner);
}
});
JFrame frame = new JFrame("Demo");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(button);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private void createAndShowParentDialog(JFrame owner) {
JButton button = new JButton("Create Child non-modal dialog");
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
JButton button = (JButton)e.getSource();
JDialog parent = (JDialog)SwingUtilities.windowForComponent(button);
Demo.this.createAndShowChildrenDialog(parent);
}
});
JDialog parentDialog = new JDialog(owner, "Parent dialog");
parentDialog.setModalityType(Dialog.ModalityType.APPLICATION_MODAL);
parentDialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
parentDialog.getContentPane().add(button);
parentDialog.pack();
parentDialog.setLocationRelativeTo(null);
parentDialog.setVisible(true);
}
private void createAndShowChildrenDialog(JDialog parent) {
JButton backButton = new JButton("Back to parent dialog");
backButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
JButton button = (JButton)e.getSource();
Window dialog = SwingUtilities.windowForComponent(button);
dialog.getOwner().toFront();
}
});
JDialog childDialog = new JDialog(parent, "Child dialog");
childDialog.setModalityType(Dialog.ModalityType.MODELESS);
childDialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
childDialog.getContentPane().add(backButton);
childDialog.pack();
childDialog.setLocationRelativeTo(null);
childDialog.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Demo().createAndShowGUI();
}
});
}
}
Edit
I can select the windows of parent and child JDialogs but when I
select the parent JDialog window, the child JDialog is still in front
of parent JDialog.
Well I have a better understanding now on what is the problem. This behaviour depends on how native windowing system handles focused and active windows. Having said this if you call for instance toFront() it will attempt to place the window at the top of the stack BUT some platforms do not allow windows which own other windows to appear on top of its childre. The same happens when you call toBack() method. See the javadocs for more details.
I've tested my code on Windows 7 (32 bits if it makes any difference) and parent dialog becomes focused but its children still showing (not focused) at the top. As mentioned above it's up to the windowing system decide how to handle this matter.
I have developed Swing application in which I have used JDialog to show popup.
But the problem is when I press alt+tab it shows only the dialog not the application. I also tried the modal for dialog.
My requirement is when the dialog opened on application and I press the alt+tab key it switch to another X application and again when I press alt+tab key it display dialog opened on my application. Currently it shows dialog opened but alone not with application.
How I can meet this requirement using JDialog?
Here is sample code
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
/**
*$Id$
*/
public class Main
{
public static void main(final String[] args)
{
final JFrame jFrame = new JFrame();
jFrame.setSize(300, 200);
final JPanel panel = new JPanel();
final JButton button = new JButton("click here to open dialog");
final ProductDialog dialog = new ProductDialog();
button.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(final ActionEvent e)
{
dialog.setVisible(true);
}
});
panel.add(button);
jFrame.add(panel);
jFrame.setVisible(true);
}
}
And The dialog is as under
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class ProductDialog extends JDialog
{
private static final long serialVersionUID = 1L;
public ProductDialog()
{
this.add(new JPanel().add(new JLabel("Test")));
this.setSize(150, 100);
this.setModal(true);
this.setLocationRelativeTo(null);
}
}
Here is an image of the visual effect of a small app. that is currently displaying a security dialog in alt+tab on Windows 7. The app. itself is already visible on-screen, though the security dialog (upper left) is all that is shown in the smaller icons.
You need to set the parent window of the dialog to the Frame of your application.
Small example:
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
public class TestDialog {
protected void initUI() {
JFrame frame = new JFrame(TestDialog.class.getSimpleName());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final JButton button = new JButton("Click me to open dialog");
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Window parentWindow = SwingUtilities.windowForComponent(button);
JDialog dialog = new JDialog(parentWindow);
dialog.setLocationRelativeTo(button);
dialog.setModal(true);
dialog.add(new JLabel("A dialog"));
dialog.pack();
dialog.setVisible(true);
}
});
frame.add(button);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new TestDialog().initUI();
}
});
}
}
I have pass the parent Frame to the Dialog as under.
final ProductDialog dialog = new ProductDialog(jFrame);
And set it as under
Call the constructor of super class with parent window as argument and set the modality type of dialog and it's work for me.
import java.awt.Dialog;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class ProductDialog extends JDialog
{
private static final long serialVersionUID = 1L;
public ProductDialog(final JFrame jFrame)
{
super(jFrame);
this.add(new JPanel().add(new JLabel("Test")));
this.setSize(150, 100);
this.setModal(true);
this.setModalityType(Dialog.ModalityType.DOCUMENT_MODAL);
}
}
This is just sample example that I have created for testing.
i want to open new JDialog box inside JDialog box. so i have used that code to prevent to come on ancestor JFrame but i am facing the problem to open new JDialog box in previous JDialog box. please give me the solution to get rid of this problem.
Here is the code :-
TestbedWorkflow tbwf = new TestbedWorkflow();
JDialog dialog = new JDialog();
Dimension s = SOAStreamer.getSOAStreamerObj().getContentPanel().getSize();
dialog.setSize(s);
dialog.setTitle("TestBed Workflow Design");
dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
dialog.setModalityType(Dialog.ModalityType.APPLICATION_MODAL);
tbwf.setSize(s);
dialog.add(tbwf);
tbwf.updateUI();
dialog.setVisible(true);
TestbedWorkflow is JFrame which i have added in to JDialog box.now i want to open new JDialog box.
thanks in advance
The example below opens an arbitrary number of dialogs in an APPLICATION_MODAL hierarchy; only the most recent is operable. As an alternative, consider a modeless dialog, illustrated here.
Update: The revised example below shows the hierarchy depth in the dialog title and eliminates a spurious subclass.
import java.awt.Dialog;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
/**
* #see https://stackoverflow.com/a/12301243/230513
*/
public class DialogTest {
private static int index;
static class OpenAction extends AbstractAction {
public OpenAction() {
super("Open");
}
#Override
public void actionPerformed(ActionEvent e) {
JDialog jd = new JDialog();
jd.setTitle("D" + String.valueOf(++index));
jd.setModalityType(Dialog.ModalityType.APPLICATION_MODAL);
jd.add(new JButton(new OpenAction()));
jd.pack();
jd.setLocationRelativeTo(null);
jd.setVisible(true);
}
}
private void display() {
JFrame f = new JFrame("DialogTest");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new JButton(new OpenAction()));
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new DialogTest().display();
}
});
}
}