Simple question:
Can a swing frame be completely modal ( block all others windows ) ?
I tried the following, but I can still click on other apps windows ( like this browser )
JDialog myDialog = ....
myDialog.setModalityType(Dialog.ModalityType.APPLICATION_MODAL);
Plase paste some code if this is possible.
Dialogs are not meant to be globally modal. Every modern OS strongly discourages global modality in its HIG, and they may even have deprecated the functionality (as indicated by the fact that you can't get it to work). Your app should never steal events from the entire system; that's not only bad design, it's near-criminal in my book.
Ignoring the fact that most people like to multi-task between several apps, what about the scenario where you open a globally modal dialog and then your application freezes? Ctrl+Alt+Del should work on Windows to kill the app, but I'm not sure about Cmd+Opt+Escape on Mac with a globally modal dialog (does Cocoa even have global modality?). None of the Linux platforms have any nice way of killing apps which have taken over complete control of the UI as you are suggesting (you would have to kill X11 completely and start a new instance from scratch).
My answer: find another way. I don't care what your client is asking for, they don't want this.
JFrame is not designed to be modal. Use JDialog for it, but you will loose some JFrame functionality doing so.
If you can't live with the loss, you have to block the EventQueue and replace it with your own to only accept events from the blocking one.
See Creating Modal Internal Frames for an explanation using internal frames that should be applicable to JFrame also.
Edit:
Oups, my answer seems a bit off, since your code example shows you are already using a Dialog subclass for this.
I don't know about global modal, but here's an idea.
Take the screenshot of the desktop.
Go full screen.
Pop up your dialog.
Since the desktop is fake screenshot, you can ignore any attempt to click into it.
Full screen sample:
private void toggleFullScreenWindow() {
GraphicsEnvironment graphicsEnvironment
= GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice graphicsDevice
= graphicsEnvironment.getDefaultScreenDevice();
if(graphicsDevice.getFullScreenWindow()==null) {
dialog.dispose(); //destroy the native resources
dialog.setUndecorated(true);
dialog.setVisible(true); //rebuilding the native resources
graphicsDevice.setFullScreenWindow(dialog);
}else{
graphicsDevice.setFullScreenWindow(null);
dialog.dispose();
dialog.setUndecorated(false);
dialog.setVisible(true);
dialog.repaint();
}
requestFocusInWindow();
}
FYI: Full-Screen Exclusive Mode API.
Related
I need my JFrame to freeze/ become inaccessible, similar to how it would with a model JDialog or setEnabled(false).
In most cases I would use JDialog but in this instance I am running a dialog through a C library.
Going down the setEnabled(false) line also doesn't work because it, on setEnabled(true), will send the window to the back. And even using toFront() will cause the window to go to the back for a split second then come to the front again.
Is there a better way to go about doing this, or an I stuck with the slight imperfection of the window flickering.
Also if you are familiar with the library I am using LWJGL's NativeFileDialog wrapper.
I have found a pretty good solution to this issue, originally answered as part of this post. It takes the idea of using a JDialog, but instead of displaying some message it is completely transparent, invisible to the user.
final JDialog modalBlocker = new JDialog();
modalBlocker.setModal(true);
modalBlocker.setUndecorated(true);
modalBlocker.setOpacity(0.0f);
modalBlocker.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
Then we can simply display our modal and show our file dialog
// Using invoke later we show our dialog after our frame has been blocked
// by setVisible(true)
SwingUtilities.invokeLater(()->{
// show dialog
});
modalBlocker.setVisible(true);
modalBlocker.dispose(); // immediately release resources
Then we can call modalBlocker.setVisible(false) at any point to stop the modality effect on our frame.
Again this is the solution that worked for me, it is not mine. The code was written to integrate JavaFX with Swing by Sergei Tachenov, all credit goes to him!
Is there a possibility to prevent a JOptionPane dialog from blocking the interaction with the rest of the program, especially child JFrames? In my GUI, I launch a JFrame and want a message dialog to pop up after the child is closed to remind the user of something, but they launch parallel and the reminder blocks the child frame from being used.
Like here:
popupObjMan newPopup1 = new popupObjMan(gatewayAbstract, gatewayAbstractID);
JOptionPane.showInternalMessageDialog(this, "REMINDER: DO REFRESH");
I've tried to set the popup always on top, but this doesn't quite do the job.
I have no problem with them launching parallel (I'd even prefer it), but I could not work my head around it yet.
I just started Java programming ,so sorry in case that'd be something obvious.
A JOptionPane normally need to be modal. It shows something important and waits till the user answers with whatever option you give him (e.g. ok-button, yes/no-buttons, ...)
But there are several ways to reach your target.
(a)
Normally a JOptionPane creates a modal window.
You need a modeless window which does not block other windows.
https://docs.oracle.com/javase/tutorial/uiswing/misc/modality.html
(b)
You can start different threads to work for your different windows. They can have windows which are shown whenever the responsible thread commands them to. This is a bit difficult and can lead to memory-troubles.
(c)
You can write your own message-panels (e.g. notificaton) which are shown when and how long you like.
Bigger projects use different of these ways to achieve their goals.
A JOptionPane is a component, just like a JPanel. As a component it can be added to any other panel.
The JOptionPane API provides static methods to create a show the JOptionPane on a modal JDialog by default. You can't change this behaviour.
However, you can manually add the JOptionPane to a non-modal JDialog that you create. This is extra work as you now need to handle the closing of the dialog and processing the clicked button.
If you really want to do this then read the JOptionPane API. There is a section on Direct Use which demonstrates the basic code needed to add the JOptionPane to a JDialog.
In my program it opens a window if an action is happened. After I have filled out information in this window, and entered a button, the window dispose().
The window is picked up in a program outside my main program, but when I close this window, my main program stops. How can I prevent this from happening?
Thanks for your help!
You can set the defalaultCloseOperation property of the second frame to DO_NOTHING_ON_CLOSE or DISPOSE_ON_CLOSE
Don't even use two frames. Use a modal JDialog instead for a secondary frame. See more at How to Use Dialogs. Read more about Modality. And for a good read, see The Use of Multiple JFrames, Good/Bad Practice?
Forget about number 1. and go straight to 2.
If using JFrame or extending it you can use setDefaultCloseOperation() method like:
frame.setDefaultCloseOperation(HIDE_ON_CLOSE);
// or
frame.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
The dispose command is from the AWT Bundle, and this may cause problems, as you are attempting to "close" a swing window with an AWT command.
You can close the window with this command:
windowName.setVisable(false);
windowName is the name of the object representing the window. If you are extending a class, and have no object, you can use this
More Information on the Dispose Method:
"In general java.awt.Window.dispose() is used on a GUI component that is
a subclass of Window, in order for that specific GUI Window object (and
its children) to properly release and destroy native UI resources (such
as the screen). Garbage collection (and the eventual exiting of the
entire VM) may happen as a result of dispose(), but is not directly
connected with the dispose() call itself." From: https://www.java.net/node/684412
windowName.setVisable(false);
doesn't seems to be a good choice. What if user want to exit the program?
check this question - How to hide a JFrame in system tray of taskbar
I want to understand how java.awt.Dialog achieves modality (blocking other windows)?
Yeah, I tried reading the code of java.awt.Dialog, but I am kind of getting lost in it. So I want to know briefly what they do. Do they disable all events of all other windows?
Thanks
Prem
Its system dependent. On windows the main event loop is modified. You are most of the time better off opening a dialog non-modal and lock the underlying window manually (e.g. set a glasspane to the rootpane and disable it, or block all events setting a custom focus manager).
I created a dialog box like this:
String response =
JOptionPane.showInputDialog(null,"message","title",JOptionPane.PLAIN_MESSAGE);
I'd like to keep it always on top of all windows.
Do you have any idea?
Thanks!
In fact, using Java, having a system modal dialog is not possible. The best you can have is a toolkit modal option pane. That's to say an option pane that stay in front of all Java windows.
This example explains how Java6 allows you to do that.
Maybe I don't get the question, but I quickly created desktop app with code you posted and it actually is modal ...