I want to show a "Confirm Close" window when closing the main app window, but without making it disappear. Right now I am using a windowsListener, and more specifially the windowsClosing event, but when using this event the main window is closed and I want to keep it opened.
Here is the code I am using:
To register the listener
this.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent evt) {
thisWindowClosing(evt);
}
});
The implementation of the handling event:
private void thisWindowClosing(WindowEvent evt) {
new closeWindow(this);
}
Also I've tried using this.setVisible(true) in the thisWindowClosing() method but it doesn't work.
Any suggestions?
package org.apache.people.mclark.examples;
import java.awt.event.*;
import javax.swing.*;
public class ClosingFrame extends JFrame {
public ClosingFrame() {
final JFrame frame = this;
// Setting DO_NOTHING_ON_CLOSE is important, don't forget!
frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
int response = JOptionPane.showConfirmDialog(frame,
"Really Exit?", "Confirm Exit",
JOptionPane.OK_CANCEL_OPTION);
if (response == JOptionPane.OK_OPTION) {
frame.dispose(); // close the window
} else {
// else let the window stay open
}
}
});
frame.setSize(320, 240);
frame.setLocationRelativeTo(null);
}
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new ClosingFrame().setVisible(true);
}
});
}
}
Related
I have this code sample in a separate jDialog (jDialog is in the same package as that of JFrame) which used to check (using a Thread) if the jCheckBox1 in the jFrame is whether visible or not. JDialog is set to visible by clicking a JLabel (Change Password) in JFrame. I have not set the visibility of the JFrame even to false even after I click on the Change Password JLabel.
The problem I encountered is that even if the JFrame is not visible i.e when I run the JDialog separately (without clicking on the Change Password JLabel) it prints the "Visible" and I'm more than sure that the jFrame is not visible and not running.
This is the code snippet (Thread) I have used to check the visibility of the JFrame's jCheckBox1:
LockOptions lock = new LockOptions();
private void setLocation2() {
new Thread() {
public void run() {
boolean running = true;
while (running) {
try {
Thread.sleep(1000);
if (lock.jCheckBox1.isVisible()) {
System.out.println("Visible");
} else {
System.out.println("Not Visible");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
}
And this is the Code I have written in JFrame's Change Password JLabel:
private void jLabel9MouseClicked(java.awt.event.MouseEvent evt) {
Container c = new ChangePassword(this, rootPaneCheckingEnabled);
if (!c.isShowing()) {
c.setVisible(true);
hideMeToSystemTray();
this.requestFocusInWindow();
}
}
But when I run the JDialog separately (without clicking on the Change Password JLabel) it prints the "Visible"
I have attached a Screenshots of both JFrame and JDialog
JFrame containing jCheckBox1
JDialog:
OK, let's have the simplest possible example.
The following code creates a main frame having a button to create a new frame of class LockOptionsWindow, which extends JFrame.
The class FrameDemo implements Runnable. So can it be accessed on the event dispatching thread using SwingUtilities.invokeLater as mentioned in Swing's Threading Policy. So it is possible creating a new thread checklockoptionswindow which then can check whether the new window created by the button is visible or not visible.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class FrameDemo extends WindowAdapter implements ActionListener, Runnable {
private LockOptionsWindow lockoptionswindow;
private Thread checklockoptionswindow = new Thread();
private void showLockOptionsWindow() {
if (lockoptionswindow != null && lockoptionswindow.isDisplayable()) {
lockoptionswindow.setVisible(true);
lockoptionswindow.setExtendedState(Frame.NORMAL);
} else {
lockoptionswindow = new LockOptionsWindow();
lockoptionswindow.setSize(new Dimension(300, 100));
lockoptionswindow.setVisible(true);
lockoptionswindow.setExtendedState(Frame.NORMAL);
}
}
private void startCheckLockOptionsWindow() {
if (!checklockoptionswindow.isAlive()) {
checklockoptionswindow = new Thread() {
public void run() {
boolean running = true;
while (running) {
try {
Thread.sleep(1000);
if (lockoptionswindow.isVisible()) {
if (lockoptionswindow.getExtendedState() == Frame.ICONIFIED) {
System.out.println("Visible iconified");
} else {
System.out.print("Visible on screen ");
int x = lockoptionswindow.getLocation().x;
int y = lockoptionswindow.getLocation().y;
System.out.println("at position " + x + ", " + y);
}
} else {
System.out.println("Not Visible");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
checklockoptionswindow.start();
}
}
public void actionPerformed(ActionEvent e) {
showLockOptionsWindow();
startCheckLockOptionsWindow();
}
public void run() {
JFrame frame = new JFrame("FrameDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JButton button = new JButton("Show LockOptions frame");
button.addActionListener(this);
Container contentPane = frame.getContentPane();
contentPane.add(button);
frame.setLocationRelativeTo(null);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new FrameDemo());
}
class LockOptionsWindow extends JFrame {
public LockOptionsWindow() {
super("LockOptions frame");
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
}
}
}
Edited to determine whether the LockOptionsWindow is visible iconified only or is really showed as window on the screen.
Is it possible to be notified whenever any window in the application was created or closed?
At the moment I'm polling Window.getWindows() but I would prefer to get notified instead.
What I have:
List<Window> previousWindows = new ArrayList<>();
while (true) {
List<Window> currentWindows = Arrays.asList(Window.getWindows());
for (Window window : currentWindows) {
if (!previousWindows.contains(window)) {
//window was created
}
}
for (Window window : previousWindows) {
if (!currentWindows.contains(window)) {
//window was closed
}
}
previousWindows = currentWindows;
Thread.sleep(1000);
}
What I'd like:
jvm.addWindowListener(this);
#Override
public void windowWasDisplayed(Window w) {
//window was created
}
#Override
public void windowWasClosed(Window w) {
//window was closed
}
You can register listeners that receive any subset of types of AWT events via the windowing Toolkit. From those you can select and handle the WindowEvents for windows being opened and closed, something like this:
class WindowMonitor implements AWTEventListener {
public void eventDispatched(AWTEvent event) {
switch (event.getID()){
case WindowEvent.WINDOW_OPENED:
doSomething();
break;
case WindowEvent.WINDOW_CLOSED:
doSomethingElse();
break;
}
}
// ...
}
class MyClass {
// alternative 1
public void registerListener() {
Toolkit.getDefaultToolkit().addAWTEventListener(new WindowMonitor(),
AWTEvent.WINDOW_EVENT_MASK);
}
// alternative 2
public void registerListener(Component component) {
component.getToolkit().addAWTEventListener(new WindowMonitor(),
AWTEvent.WINDOW_EVENT_MASK);
}
}
I would recommend alternative 2, where the Component from which you obtain the Toolkit is the main frame of your application (there should be only one), but alternative 1 should work out for you if you have to do this without reference to any particular component (for instance, before any have been created).
Do note, however, that registering an AWTEventListener is subject to a security check.
If you create the additional windows (I assume JFrames) yourself, you can use the addWindowListener method. The WindowAdapter abstract class allows you to override methods for the events you are interested in:
import java.awt.event.*;
import javax.swing.*;
public class MultipleWindows {
public static void main(String[] arguments) {
SwingUtilities.invokeLater(() -> new MultipleWindows().createAndShowGui());
}
private void createAndShowGui() {
JFrame frame = new JFrame("Stack Overflow");
frame.setBounds(100, 100, 800, 600);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
JPanel panel = new JPanel();
panel.add(new JLabel("Testing multiple windows..."));
frame.getContentPane().add(panel);
WindowAdapter windowAdapter = new WindowAdapter() {
#Override
public void windowOpened(WindowEvent windowEvent) {
System.out.println("Window opened: "
+ windowEvent.getWindow().getName());
}
#Override
public void windowClosed(WindowEvent windowEvent) {
System.out.println("Window closed: "
+ windowEvent.getWindow().getName());
}
};
for (int windowIndex = 2; windowIndex < 6; windowIndex++) {
String title = "Window " + windowIndex;
JFrame extraFrame = new JFrame(title);
extraFrame.setName(title);
extraFrame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
extraFrame.addWindowListener(windowAdapter);
extraFrame.setVisible(true);
}
frame.setVisible(true);
}
}
I would like to listen to events when clicked on Ok and Cancel buttons in CheckBoxListComboBox Does any one know how to register for events on Ok and Cancel buttons? If the events registration is not possible, can we override the Ok and cancel buttons of our own?
It seems there is no option to register a listener. However, you can override getDialogOKAction() and getDialogCancelAction(). You can also override createListChooserPanel() and provide you own actions there.
For example:
import java.awt.event.ActionEvent;
import javax.swing.*;
import com.jidesoft.combobox.CheckBoxListComboBox;
public class TestCheckboxList extends JPanel{
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationByPlatform(true);
String[] items = {"Item1", "Item2", "Item3"};
frame.add(new CheckBoxListComboBox(items){
#Override
protected Action getDialogOKAction() {
return new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("OK");
}
};
}
#Override
protected Action getDialogCancelAction() {
return new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("Cancel");
}
};
}
});
frame.pack();
frame.setVisible(true);
}
});
}
}
I looking for create mechanism for messaging when exiting and changes has been made.
I want it to display a messagebox asking the user :
( Are you sure you don't want to save the changes - yes / no)
Upon closing the form by clicking on the button named 'Exit' or when use close button, ''X". Don't know the syntax for it, can someone help me please?
Here's some basic code on how to do it:
public class ClosingFrame extends JFrame {
public ClosingFrame() {
super("Shutdown hook");
setSize(400, 400);
setLocationByPlatform(true);
setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); /* important */
addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(WindowEvent e) {
super.windowClosing(e);
int showConfirmDialog = JOptionPane.
showConfirmDialog(ClosingFrame.this, "Do you want to save?");
if (showConfirmDialog == JOptionPane.YES_OPTION) {
System.out.println("saved");
System.exit(0);
} else if (showConfirmDialog == JOptionPane.NO_OPTION) {
System.out.println("not saved");
System.exit(0);
} else {
System.out.println("aborted");
// do nothing
}
}
});
setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> new ClosingFrame());
}
}
The applet consists of following code:
public class TestApplet extends Applet {
public TestApplet() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JDialog dialog = new JDialog();
dialog.setContentPane(new JLabel("Hello"));
dialog.setSize(new Dimension(300, 200));
dialog.setModal(true);
dialog.setVisible(true);
}
});
}}
When I open it on InternetExplorer running on Windows 7 it works: I change browser tabs, dialog always stays in front.
When I open it on Firefox ESR 10.0.5 running on Red Hat Enterprise Linux Server Release 6.3, Java 1.7.0_07-b10 then it instantly goes behind the Browser window and I have to minimize browser in order to find it again.
What do I have to do to make the modal dialog always stay in front of the Applet?
Update:
Changing creation of JDialog to
JDialog dialog = new JDialog(javax.swing.SwingUtilities.getWindowAncestor(TestApplet.this));
makes not difference.
Finally, after trying alot of things I figured out the following workaround:
public class ModalDialog extends JDialog {
private boolean isClosing = false;
protected synchronized boolean isClosing() {
return isClosing;
}
protected synchronized void setClosing(boolean isClosing) {
this.isClosing = isClosing;
}
public ModalDialog() {
setSize(200, 300);
setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
addFocusListener(new FocusAdapter() {
public void focusLost(FocusEvent arg0) {
if (isClosing()) {
System.out.println("Returned because dialog is already closing");
return;
}
EventQueue.invokeLater(new Runnable() {
public void run() {
ModalDialog.this.setVisible(false);
ModalDialog.this.setVisible(true);
}
});
}
});
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.out.println("Dialog is closing");
setClosing(true);
}
});
}
}