问题
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;
}
回答1:
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);
}
});
}
}
回答2:
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.
回答3:
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.
来源:https://stackoverflow.com/questions/30968938/unable-to-close-joptionpane-properly-in-chain-order