I want JOptionPane to appear above modeless dialogs. For example, in the following app please press the JDialog button to show a modeless dialog, and then press the JOptionPane button to show a JOptionPane confirmation dialog. Unfortunately, the JOptionPane appears under the modeless dialog.
In my real app, I have several modeless JDialogs, and I use JOptionPane from several different places.
How can I easily make the JOptionPane appear above all the modeless JDialog instances?
By "easily" I mean by adding 1 or 2 lines to each modeless JDialog construction or to each JOptionPane invocation.
One way I tried was to make a new temporary unowned JFrame with always-on-top option as the owner of the JOptionPane. This makes the JOptionPane on top, but the JOptionPane is in center of the screen instead of the center of original JFrame, and I worry that the user may not notice it.
Another way I tried was to make all modeless dialogs invisible before showing the JOptionPane and then making them visible again afterward. But this way is not easy to put round all calls to JOptionPane, because (I believe) it requires a try-finally block to do reliably.
import java.awt.BorderLayout;
import java.awt.event.*;
import javax.swing.*;
public class App {
public static void main(String[] args) {
JFrame f = new JFrame("App Frame");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JButton btnDialog = new JButton("JDialog");
JButton btnOptionPane = new JButton("JOptionPane");
btnDialog.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JDialog dlg = new JDialog(f, "Modeless Dialog", false);
dlg.setSize(256, 256);
dlg.setLocationRelativeTo(f);
dlg.setVisible(true);
}
});
btnOptionPane.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JOptionPane.showConfirmDialog(f, "Confirm JOptionPane");
}
});
f.add(btnDialog, BorderLayout.WEST);
f.add(btnOptionPane, BorderLayout.EAST);
f.setSize(512, 512);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
}
You need to set the correct parent for your option pane. To determine it you can use the list of all opened windows. In my example I use the last opened window.
import java.awt.BorderLayout;
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.JOptionPane;
public class App {
public static void main(String[] args) {
JFrame f = new JFrame("App Frame");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JButton btnDialog = new JButton("JDialog");
JButton btnOptionPane = new JButton("JOptionPane");
btnDialog.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
JDialog dlg = new JDialog(f, "Modeless Dialog", false);
dlg.setSize(256, 256);
dlg.setLocationRelativeTo(f);
dlg.setVisible(true);
}
});
btnOptionPane.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
JOptionPane.showConfirmDialog(findLatestWindow(), "Confirm JOptionPane");
}
});
f.add(btnDialog, BorderLayout.WEST);
f.add(btnOptionPane, BorderLayout.EAST);
f.setSize(512, 512);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
private static Window findLatestWindow() {
Window result = null;
for (Window w : Window.getWindows()) {
if (w.isVisible()) {
result = w;
}
}
return result;
}
}
If you have more than one dialog opened at the same time, and user can switch between these dialogs, so you need some more lines of code. Because in your case after button click the frame is always the focus owner.
After trying and experimenting with #Sergiy's idea of using static Window methods I came up with this:
import java.awt.BorderLayout;
import java.awt.Window;
import java.awt.event.*;
import java.util.ArrayList;
import javax.swing.*;
public class App {
static JFrame hideOwnedWindows(JFrame f) {
ArrayList<Window> arHidden = new ArrayList();
WindowAdapter wa = new WindowAdapter() {
#Override
public void windowActivated(WindowEvent e) {
for (Window w : arHidden)
w.setVisible(true);
f.removeWindowListener(this);
}
};
for (Window w : f.getOwnedWindows()) {
if (w.isVisible()) {
w.setVisible(false);
arHidden.add(w);
}
}
f.addWindowListener(wa);
return f;
}
public static void main(String[] args) {
JFrame f = new JFrame("App Frame");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JButton btnDialog = new JButton("JDialog");
JButton btnOptionPane = new JButton("JOptionPane");
btnDialog.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JDialog dlg = new JDialog(f, "Modeless Dialog", false);
dlg.setSize(256, 256);
dlg.setLocationRelativeTo(f);
dlg.setVisible(true);
}
});
btnOptionPane.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JOptionPane.showConfirmDialog(hideOwnedWindows(f), "Confirm JOptionPane");
}
});
f.add(btnDialog, BorderLayout.WEST);
f.add(btnOptionPane, BorderLayout.EAST);
f.setSize(512, 512);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
}
The "hideOwnedWindows" method hides all owned windows including the dialogs, and then restores them next time the main JFrame is activated. As all owned Windows are invisible during the JOptionPane, I think (hope) the main JFrame is always activated when the JOptionPane closes.
Related
I am quite new to Java and only after researching and googling and reading many answers, I am posting this. I am kinda lost. A little guidance would be of great help. The following is a method from a class that implements the "ActionListener" interface. What I am trying to do is this: There is a button which one clicked should open a new window with two options in the form of two Radio Buttons. I need to know the Radio Button which was selected for further use in my code. I declared, the "scoreOption" variable as a class variable and static, and then attempt to update it in the "actionPerformed" abstract method. But when I refer to it (after the method call), the value stays the same - null, or whatever I set it to initially. Here is the code:
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileNotFoundException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Scanner;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JTextArea;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class StartEvents implements ActionListener {
StartPanel startingPanel;
static String scoreOption;
public StartEvents(StartPanel startPanel) {
startingPanel = startPanel;
}
// Scoring System Window - 1
public void scoringSystem() {
startingPanel.scoringSystem.addActionListener(new ActionListener () {
#Override
public void actionPerformed(ActionEvent e) {
Panel scoringSystemPanel = new Panel();
JFrame scoreSystemFrame = scoringSystemPanel.frame(150, 250, "Scoring System", 2, true);
JPanel scoreSystemPanel = scoringSystemPanel.panel(Color.lightGray);
JButton confirmSelection = scoringSystemPanel.button(40, 20, "Confirm");
JRadioButton scoreSystem1 = scoringSystemPanel.radioButton("Option 1: Same Points Per Hit");
scoreSystem1.setActionCommand("Option 1");
JRadioButton scoreSystem2 = scoringSystemPanel.radioButton("Option 2: Unique Points Per Hit");
scoreSystem2.setActionCommand("Option 2");
ButtonGroup scoreSys = new ButtonGroup();
scoreSys.add(scoreSystem1);
scoreSys.add(scoreSystem2);
scoreSystemFrame.getContentPane().add(scoreSystemPanel);
scoreSystemPanel.add(scoreSystem1);
scoreSystemPanel.add(scoreSystem2);
scoreSystemPanel.add(confirmSelection);
// Get Selection Event
// Option 1
scoreSystem1.addActionListener(new ActionListener () {
#Override
public void actionPerformed(ActionEvent e) {
if (scoreSystem1.isSelected()) {
scoreOption = scoreSystem1.getActionCommand();
}
}
});
// Option 2
scoreSystem2.addActionListener(new ActionListener () {
#Override
public void actionPerformed(ActionEvent e) {
if (scoreSystem2.isSelected()) {
scoreOption = scoreSystem2.getActionCommand();
}
}
});
// Confirm Event
confirmSelection.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
scoreSystemFrame.dispose();
}
});
}
});
}
Main Game Class where the method scoringsystem is called.
import java.util.ArrayList;
public class Game {
public static void main(String[] args) {
StartPanel startingPanel = new StartPanel();
startingPanel.makeStartPanel();
StartEvents starter = new StartEvents(startingPanel);
starter.rulesButton();
starter.exitButton();
starter.highScoresButton();
ArrayList<Integer> dimensions = starter.boardSizeSelector();
// Problem Zone
System.out.println(StartEvents.scoreOption);
starter.scoringSystem();
System.out.println(StartEvents.scoreOption);
// The two values of scoreOption should be different
String[] playPanelDetails = {"970", "Player 1", "450"};
// Final Start of the Game
starter.startGameButton(playPanelDetails, dimensions);
}
}
Furthermore, could you please let me know regarding the following questions:
Implementing "ActionListener" within another "ActionListener" is recommended? Good Practice?
Can there only be one declaration of the "actionPerformed" method or can it be overloaded too?
Is it possible to get a return value from "actionPerformed" method?
I would be really grateful if even some hints could be provided. I really tried a lot and only then posting it here. Thank you very much in advance.
Small Edit: When I "System.out.println" the "actioncommand" there itself, it does work perfectly, printing in the console. But not when I try to update the class variable and then try to print it after the method call. Dunno if this helps.
JFrames are not modal -- you create one and display it, it does not block the code flow, and so you are extracting the value of scoreOption right as the JFrame is being displayed and before the user has had any chance to change it. You need to use a modal dialog such as a JDialog that is created as a modal dialog or use a JOptionPane (which is actually just a modal JDialog under the hood). This will block the flow of code so that you extract the data only after it has been changed by the user.
An example that proves the point:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class FooGui01 extends JPanel {
private String frameTest = "";
private String dialogTest = "";
private JFrame mainFrame = new JFrame("Main GUI");
private JFrame subFrame;
private JDialog dialog;
public FooGui01() {
JButton showFrameBtn = new JButton("Show JFrame");
showFrameBtn.addActionListener(e -> {
changeTest1WithJFrame();
System.out.println("frameTest: " + frameTest);
});
JButton showDialogBtn = new JButton("Show JDialog");
showDialogBtn.addActionListener(e -> {
changeTest2WithModalDialog();
System.out.println("dialogTest: " + dialogTest);
});
JPanel panel = new JPanel();
panel.add(showDialogBtn);
panel.add(showFrameBtn);
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainFrame.add(panel);
mainFrame.pack();
mainFrame.setLocationByPlatform(true);
mainFrame.setVisible(true);
}
public void changeTest1WithJFrame() {
if (subFrame == null) {
subFrame = new JFrame("Frame");
JButton button = new JButton("Press me");
button.addActionListener(e -> {
frameTest = "Hello World and frameTest";
subFrame.setVisible(false);
});
JPanel panel = new JPanel();
panel.add(button);
subFrame.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
subFrame.add(panel);
subFrame.pack();
subFrame.setLocationByPlatform(true);
}
subFrame.setVisible(true);
}
public void changeTest2WithModalDialog() {
if (dialog == null) {
dialog = new JDialog(mainFrame, "Dialog", Dialog.ModalityType.APPLICATION_MODAL);
JButton button = new JButton("Press me");
button.addActionListener(e -> {
dialogTest = "Hello World and dialogTest";
dialog.setVisible(false);
});
JPanel panel = new JPanel();
panel.add(button);
dialog.add(panel);
dialog.pack();
dialog.setLocationByPlatform(true);
}
dialog.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> new FooGui01());
}
}
If you run the code, when you show the sub JFrame, the test text is displayed immediately in the console before the dialog has been dealt with. If you press the button to show the dialog, the test text display is delayed until after the button has been pushed, changing the text.
Pressing the frame button twice will finally show the correct text since the text was set by the first time it was displayed.
A JDialig is just like a JFrame. That is you add components to it like you do any frame.
The difference is that you can make a JDialog modal. This means that when you use:
dialog.setVisible(true);
System.out.println("here");
The code after the setVisible(...) statement will not be executed until the dialog is closed. It also means you can't click on the parent JFrame until the dialog is closed.
An easy way to create a modal JDialog is to use a JOptionPane. It has some predefined methods that make prompting for user input easy.
For example in your case you could do something like:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class SSCCE extends JPanel
{
private int scoringOption = -1;
public SSCCE()
{
JButton button = new JButton("Change Points Option");
add(button);
button.addActionListener((e) -> displayOptionDialog());
}
private void displayOptionDialog()
{
Window window = SwingUtilities.windowForComponent( this );
// Custom button text
Object[] options = {"Option 1: Same Points Per Hit", "Option 2: Unique Points Per Hit"};
scoringOption = JOptionPane.showOptionDialog(
window,
"Select your scoring option:",
"Scoring Option",
JOptionPane.YES_NO_CANCEL_OPTION,
JOptionPane.QUESTION_MESSAGE,
null,
options,
null);
System.out.println( scoringOption );
}
private static void createAndShowGUI()
{
JFrame frame = new JFrame("SSCCE");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new SSCCE());
frame.pack();
frame.setLocationByPlatform( true );
frame.setVisible( true );
}
public static void main(String[] args) throws Exception
{
java.awt.EventQueue.invokeLater( () -> createAndShowGUI() );
}
}
The above is also an example of an "MRE". The code is simple and contained in a single class that you can copy/paste/compile and test.
Read the section from the Swing tutorial on How to Use Dialogs for more examples of using a JOptionPane.
If you really want to use radio buttons, then you can create a panel with the radio buttons and display them on the option pane using the showConfirmDialog(...) method. When the dialog closes you would then need to get the action command from the ButtonModel of the ButtonGroup.
See: how to set & manage the layout of JOptionPane for a basic example of this approach to get you started.
I'm trying to use a few JDialogs inside my form JPanel to notify the user of incorrect data and form submission.
I'm just a bit confused with the JDialog constructor. I'd want to link the dialog to the panel (only because that's where it's created), but obviously the only owner parameters that are allowed are top level Frames (which I don't think I can access from the JPanel), or a Dialog (which I can't see helping me).
I could pass a reference for the Frame down to the JPanel, but isn't that a bit strange design wise? Or am I misunderstanding the class, or just more generally where the JDialog should be instantiated?
Hope I've made myself clear, I can make a sscce if it helps. Thanks.
the only owner parameters that are allowed are top level Frames (which I don't think I can access from the JPanel
You can access the parent frame of the panel by using:
Window window = SwingUtilities.windowForComponent( yourPanelHere );
Then just use the window as the owner of the dialog.
JComponent.getTopLevelAncestor gives you the owner of the JPanel:
Returns the top-level ancestor of this component (either the
containing Window or Applet), or null if this component has not been
added to any container.
You can try it:
import java.awt.BorderLayout;
import java.awt.EventQueue;
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.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
public class DialogTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
EventQueue.invokeLater(new Runnable() {
public void run() {
DialogFrame frame = new DialogFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
});
}
}
/**
* Frame contains menu. When we choose menu "File-> About" JDialog will be shown
*/
class DialogFrame extends JFrame {
public DialogFrame() {
setTitle("DialogTest");
setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
// Menu
JMenuBar menuBar = new JMenuBar();
setJMenuBar(menuBar);
JMenu fileMenu = new JMenu("File");
menuBar.add(fileMenu);
// Add About & Exit.
// Choose About - > About
JMenuItem aboutItem = new JMenuItem("About");
aboutItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
if (dialog == null) //if not
{
dialog = new AboutDialog(DialogFrame.this);
}
dialog.setVisible(true); // to show dialog
}
});
fileMenu.add(aboutItem);
// When Exit
JMenuItem exitItem = new JMenuItem("Exit");
exitItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
System.exit(0);
}
});
fileMenu.add(exitItem);
}
public static final int DEFAULT_WIDTH = 300;
public static final int DEFAULT_HEIGHT = 200;
private AboutDialog dialog;
}
/*
* Modal dialog waits on click
*/
class AboutDialog extends JDialog {
public AboutDialog(JFrame owner) {
super(owner, "About DialogTest", true);
// Mark with HTML centration
add(new JLabel(
"<html><h1><i>Все о Java</i></h1><hr>"
+ "Something about java and JDialog</html>"),
BorderLayout.CENTER);
// When push "ok" dialog window will be closed
JButton ok = new JButton("ok");
ok.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
setVisible(false);
}
});
// Button ОК down of panel
JPanel panel = new JPanel();
panel.add(ok);
add(panel, BorderLayout.SOUTH);
setSize(260, 160);
}
}
I have created one GUI in which I have used a JFrame. How should I make it Modal?
Your best bet is to use a JDialog instead of a JFrame if you want to make the window modal. Check out details on the introduction of the Modality API in Java 6 for info. There is also a tutorial.
Here is some sample code which will display a JPanel panel in a JDialog which is modal to Frame parentFrame. Except for the constructor, this follows the same pattern as opening a JFrame.
final JDialog frame = new JDialog(parentFrame, frameTitle, true);
frame.getContentPane().add(panel);
frame.pack();
frame.setVisible(true);
Edit: updated Modality API link & added tutorial link (nod to #spork for the bump).
You can create a class that is passed a reference to the parent JFrame and holds it in a JFrame variable. Then you can lock the frame that created your new frame.
parentFrame.disable();
//Some actions
parentFrame.enable();
just replace JFrame to JDialog in class
public class MyDialog extends JFrame // delete JFrame and write JDialog
and then write setModal(true); in constructor
After that you will be able to construct your Form in netbeans
and the form becomes modal
Create a new JPanel form
Add your desired components and code to it
YourJPanelForm stuff = new YourJPanelForm();
JOptionPane.showMessageDialog(null,stuff,"Your title here bro",JOptionPane.PLAIN_MESSAGE);
Your modal dialog awaits...
As far as I know, JFrame cannot do Modal mode. Use JDialog instead and call setModalityType(Dialog.ModalityType type) to set it to be modal (or not modal).
If you're prepared to use a JDialog instead of a JFrame, you can set the ModalityType to APPLICATION_MODAL.
This provides identical behaviour to your typical JOptionPane:
import java.awt.event.ActionEvent;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionListener;
public class MyDialog extends JFrame {
public MyDialog() {
setBounds(300, 300, 300, 300);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
setLayout(new FlowLayout());
JButton btn = new JButton("TEST");
add(btn);
btn.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e) {
showDialog();
}
});
}
private void showDialog()
{
JDialog dialog = new JDialog(this, Dialog.ModalityType.APPLICATION_MODAL);
//OR, you can do the following...
//JDialog dialog = new JDialog();
//dialog.setModalityType(Dialog.ModalityType.APPLICATION_MODAL);
dialog.setBounds(350, 350, 200, 200);
dialog.setVisible(true);
}
public static void main(String[] args)
{
new MyDialog();
}
}
This static utility method shows a modal JFrame by secretly opening a modal JDialog, too. I used this successfully and with proper behavior on Windows 7, 8, and 10-with-multiple-desktops.
It's a nice example for the very rarely used feature of local classes.
import javax.swing.*;
import java.awt.Dialog;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
// ... (class declaration)
/**
* Shows an already existing JFrame as if it were a modal JDialog. JFrames have the upside that they can be
* maximized.
* <p>
* A hidden modal JDialog is "shown" to effect the modality.
* <p>
* When the JFrame is closed, this method's listener will pick up on that, close the modal JDialog, and remove the
* listener.
*
* made by dreamspace-president.com
*
* #param window the JFrame to be shown
* #param owner the owner window (can be null)
* #throws IllegalArgumentException if argument "window" is null
*/
public static void showModalJFrame(final JFrame window, final Frame owner) {
if (window == null) {
throw new IllegalArgumentException();
}
window.setModalExclusionType(Dialog.ModalExclusionType.APPLICATION_EXCLUDE);
window.setVisible(true);
window.setAlwaysOnTop(true);
final JDialog hiddenDialogForModality = new JDialog(owner, true);
final class MyWindowCloseListener extends WindowAdapter {
#Override
public void windowClosed(final WindowEvent e) {
window.dispose();
hiddenDialogForModality.dispose();
}
}
final MyWindowCloseListener myWindowCloseListener = new MyWindowCloseListener();
window.addWindowListener(myWindowCloseListener);
final Dimension smallSize = new Dimension(80, 80);
hiddenDialogForModality.setMinimumSize(smallSize);
hiddenDialogForModality.setSize(smallSize);
hiddenDialogForModality.setMaximumSize(smallSize);
hiddenDialogForModality.setLocation(-smallSize.width * 2, -smallSize.height * 2);
hiddenDialogForModality.setVisible(true);
window.removeWindowListener(myWindowCloseListener);
}
The only code that have worked for me:
childFrame.setAlwaysOnTop(true);
This code should be called on the main/parent frame before making the child/modal frame visible. Your child/modal frame should also have this code:
parentFrame.setFocusableWindowState(false);
this.mainFrame.setEnabled(false);
What I've done in this case is, in the primary jframe that I want to keep visible (for example, a menu frame), I deselect the option focusableWindowState in the property window so It will be FALSE. Once that is done, the jframes I call don´t lose focus until I close them.
As others mentioned, you could use JDialog. If you don't have access to the parent frame or you want to freeze the hole application just pass null as a parent:
final JDialog frame = new JDialog((JFrame)null, frameTitle, true);
frame.setModal(true);
frame.getContentPane().add(panel);
frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
frame.pack();
frame.setVisible(true);
There's a bit of code that might help:
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
public class ModalJFrame extends JFrame {
Object currentWindow = this;
public ModalJFrame()
{
super();
super.setTitle("Main JFrame");
super.setSize(500, 500);
super.setResizable(true);
super.setLocationRelativeTo(null);
JMenuBar menuBar = new JMenuBar();
super.setJMenuBar(menuBar);
JMenu fileMenu = new JMenu("File");
JMenu editMenu = new JMenu("Edit");
menuBar.add(fileMenu);
menuBar.add(editMenu);
JMenuItem newAction = new JMenuItem("New");
JMenuItem openAction = new JMenuItem("Open");
JMenuItem exitAction = new JMenuItem("Exit");
JMenuItem cutAction = new JMenuItem("Cut");
JMenuItem copyAction = new JMenuItem("Copy");
JMenuItem pasteAction= new JMenuItem("Paste");
fileMenu.add(newAction);
fileMenu.add(openAction);
fileMenu.addSeparator();
fileMenu.add(exitAction);
editMenu.add(cutAction);
editMenu.add(copyAction);
editMenu.addSeparator();
editMenu.add(pasteAction);
newAction.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent arg0)
{
JFrame popupJFrame = new JFrame();
popupJFrame.addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
((Component) currentWindow).setEnabled(true); }
});
((Component) currentWindow).setEnabled(false);
popupJFrame.setTitle("Pop up JFrame");
popupJFrame.setSize(400, 500);
popupJFrame.setAlwaysOnTop(true);
popupJFrame.setResizable(false);
popupJFrame.setLocationRelativeTo(getRootPane());
popupJFrame.setVisible(true);
popupJFrame.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
}
});
exitAction.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent arg0)
{
System.exit(0);
}
});
}
public static void main(String[] args) {
ModalJFrame myWindow = new ModalJFrame();
myWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
myWindow.setVisible(true);
}
}
not sure the contetns of your JFrame, if you ask some input from users, you can use JOptionPane, this also can set JFrame as modal
JFrame frame = new JFrame();
String bigList[] = new String[30];
for (int i = 0; i < bigList.length; i++) {
bigList[i] = Integer.toString(i);
}
JOptionPane.showInputDialog(
frame,
"Select a item",
"The List",
JOptionPane.PLAIN_MESSAGE,
null,
bigList,
"none");
}
The most simple way is to use pack() method before visualizing the JFrame object. here is an example:
myFrame frm = new myFrame();
frm.pack();
frm.setVisible(true);
I have noticed that all JOptionPane method "interfere" with ActionListeners.
I need ActionListener to remain active after a JOptionPane has been opened.
For example:
I have a JButton, I register the mouse being pressed and draw the button red. Upon being released, I draw it blue.
If I just click it, the button will turn blue. Ok
If I hold it clicked, the button will stay red. Ok
If I click it and set it to open a JOptionPane dialog, it stays red, even though I have released the mouse. Not Ok
I haven't been able to find any documentation on this specific behaviour, can someone point me in the right direction?
I do really need to use JOptionPane.
One option -- queue the call to open the JOptionPane on the Swing event queue. This will delay the opening of the modal JOptionPane just a little bit, allowing other button actions to be performed.
Another option is to extract the JDialog from the JOptionPane, and call it in a non-modal way.
For example:
import java.awt.Color;
import java.awt.Component;
import java.awt.Dialog.ModalityType;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class TestOptionPane extends JPanel {
private static final Color FOREGROUND = Color.RED;
private static final Color PRESSED_FG = Color.BLUE;
private JButton button1 = new JButton(new Button1Action());
private JButton button2 = new JButton(new Button1Action());
public TestOptionPane() {
setPreferredSize(new Dimension(600, 450));
button1.getModel().addChangeListener(new ButtonModelListener(button1));
button1.setForeground(FOREGROUND);
add(button1);
button2.getModel().addChangeListener(new ButtonModelListener(button2));
button2.setForeground(FOREGROUND);
add(button2);
}
private class Button1Action extends AbstractAction {
public Button1Action() {
super("Queue JOptionPane on Swing event thread");
}
#Override
public void actionPerformed(ActionEvent e) {
SwingUtilities.invokeLater(() -> {
JOptionPane.showMessageDialog(TestOptionPane.this, "hello");
});
}
}
private class Button2Action extends AbstractAction {
public Button2Action() {
super("Show non-modal JOptionPane");
}
#Override
public void actionPerformed(ActionEvent e) {
SwingUtilities.invokeLater(() -> {
Component parentComponent = TestOptionPane.this;
JOptionPane optionPane = new JOptionPane("Hello", JOptionPane.PLAIN_MESSAGE);
JDialog dialog = optionPane.createDialog(parentComponent, "Fubars Rule!");
dialog.setModalityType(ModalityType.MODELESS);
dialog.setLocationRelativeTo(parentComponent);
dialog.setVisible(true);
});
}
}
private class ButtonModelListener implements ChangeListener {
private JButton button;
public ButtonModelListener(JButton button) {
this.button = button;
}
#Override
public void stateChanged(ChangeEvent e) {
ButtonModel model = (ButtonModel) e.getSource();
if (model.isPressed()) {
button.setForeground(PRESSED_FG);
} else {
button.setForeground(FOREGROUND);
}
}
}
private static void createAndShowGui() {
JFrame frame = new JFrame("TestOptionPane");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new TestOptionPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
package sample;
import java.awt.DisplayMode;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JDesktopPane;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
public class NewClass {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
final JFrame frame = new JFrame();
final JDesktopPane d = new JDesktopPane();
frame.setTitle("Frame");
frame.setSize(800, 600);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
GraphicsDevice device = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
device.setFullScreenWindow(frame);
device.setDisplayMode(new DisplayMode(800, 600, 32, 60));
frame.setVisible(true);
JButton btn = new JButton();
btn.setText("Button");
final JPanel panel = new JPanel();
panel.add(btn);
frame.add(panel);
final JFileChooser chooser = new JFileChooser();
chooser.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (e.getActionCommand().equals(JFileChooser.APPROVE_SELECTION)) {
System.out.println("File selected: " + chooser.getSelectedFile());
chooser.getFocusCycleRootAncestor().setVisible(false);
} else {
chooser.getFocusCycleRootAncestor().setVisible(false);
}
}
});
btn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
JOptionPane.showInternalOptionDialog(frame.getContentPane(), chooser, "Browse", JOptionPane.DEFAULT_OPTION, JOptionPane.PLAIN_MESSAGE, null, new Object[]{}, null);
}
});
}
}
This code looks weird for you, but thats the only way to preserve my full screen using GraphicsDevice. My problem is that, when I click the cancel or open button of the JFileChooser, my screen freezes using this code chooser.getFocusCycleRootAncestor().setVisible(false);. How can I close the JOPtionPane using internal dialog without freezing my screen or closing the whole screen.
you problem is not in
chooser.getFocusCycleRootAncestor().setVisible(false);
if you make these changes, your code will work flawlessly
just remove this part
JOptionPane.showInternalOptionDialog(frame.getContentPane(),chooser, "Browse",JOptionPane.DEFAULT_OPTION, JOptionPane.PLAIN_MESSAGE, null, new Object[]{}, null);
and add this code instead
chooser.showOpenDialog(frame);
let me know if you have further concerns
The problem is, the program still thinks that there is a modal dialog open, which is restricting focus to the modal dialog...
Try changing your chooser's actionListener to something like this...
chooser.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Container parent = chooser.getParent();
while (!(parent instanceof JOptionPane)) {
parent = parent.getParent();
}
JOptionPane op = (JOptionPane) parent;
op.setValue("done");
if (e.getActionCommand().equals(JFileChooser.APPROVE_SELECTION)) {
System.out.println("File selected: " + chooser.getSelectedFile());
} else {
}
}
});
This basically "tricks" the JOptionPane into thinking that the user has selected a value (which you've actually not provided anything for) and closes the dialog, returning control back to your application