I am making a word processor application in order to practise Java and I would like it so that when the user attempts to close the appliction, a JFrame will come up asking to save changes.
I was thinking about setDefaultCloseOperation() but I have had little luck so far. I would also like it to appear whent he user clicks the "X" on the top right of the window aswell if possible.
You can set the JFrame DefaultCloseOperation to something like DO_NOTHING, and then, set a WindowsListener to grab the close event and do what you want. I'll post an exemple in a few minutes .
EDIT: Here's the example :
public static void main(String[] args) {
final JFrame frame = new JFrame("Test Frame");
frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
frame.setSize(800, 600);
frame.addWindowListener(new WindowAdapter() {
//I skipped unused callbacks for readability
#Override
public void windowClosing(WindowEvent e) {
if(JOptionPane.showConfirmDialog(frame, "Are you sure ?") == JOptionPane.OK_OPTION){
frame.setVisible(false);
frame.dispose();
}
}
});
frame.setVisible(true);
}
import java.awt.event.*;
import javax.swing.*;
public class QuickGuiTest {
public static void main(String[] args) {
Runnable r = new Runnable() {
#Override
public void run() {
final JFrame frame = new JFrame("Test Frame");
frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
frame.setSize(600, 400);
frame.addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(WindowEvent e) {
int result = JOptionPane.showConfirmDialog(
frame, "Are you sure?");
if( result==JOptionPane.OK_OPTION){
// NOW we change it to dispose on close..
frame.setDefaultCloseOperation(
JFrame.DISPOSE_ON_CLOSE);
frame.setVisible(false);
frame.dispose();
}
}
});
frame.setVisible(true);
}
};
SwingUtilities.invokeLater(r);
}
}
You have to add a WindowListener to the JFrame.
Inside the windowClosing method, you can provide required code.
For example:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class ClosingFrame extends JFrame {
private JMenuBar MenuBar = new JMenuBar();
private JFrame frame = new JFrame();
private static final long serialVersionUID = 1L;
private JMenu File = new JMenu("File");
private JMenuItem Exit = new JMenuItem("Exit");
public ClosingFrame() {
File.add(Exit);
MenuBar.add(File);
Exit.addActionListener(new ExitListener());
WindowListener exitListener = new WindowAdapter() {
#Override
public void windowClosing(WindowEvent e) {
int confirm = JOptionPane.showOptionDialog(frame,
"Are You Sure to Close this Application?",
"Exit Confirmation", JOptionPane.YES_NO_OPTION,
JOptionPane.QUESTION_MESSAGE, null, null, null);
if (confirm == JOptionPane.OK_OPTION) {
System.exit(0);
}
}
};
frame.addWindowListener(exitListener);
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
frame.setJMenuBar(MenuBar);
frame.setPreferredSize(new Dimension(400, 300));
frame.setLocation(100, 100);
frame.pack();
frame.setVisible(true);
}
private class ExitListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
int confirm = JOptionPane.showOptionDialog(frame,
"Are You Sure to Close this Application?",
"Exit Confirmation", JOptionPane.YES_NO_OPTION,
JOptionPane.QUESTION_MESSAGE, null, null, null);
if (confirm == JOptionPane.OK_OPTION) {
System.exit(0);
}
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
ClosingFrame cf = new ClosingFrame();
}
});
}
}
Related
private void close () {
WindowEvent winClosing;
winClosing = new WindowEvent(this,WindowEvent.WINDOW_CLOSING);
Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(winClosing);
}
i am trying to close the previous Jframe with help of close function mentioned above by putting this code in the back button highlighted in the picture attached
this.close();
MainMenu obj = new MainMenu();
obj.setVisible(true);
problem is that above code closes my whole application instead of closing the frame which is now activated
Here is a quick demo of (what I think) you are trying to do.
Please note:
a. I do not think it is the right approach to achieve this functionality. Consider using JDialog or internal frames for the secondary windows.
b. Look at it as an example of an MCVE. In fact it would have been much better to demonstrate the issue using one secondary frame, instead of two.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JButton;
import javax.swing.JFrame;
public class MainWindow extends JFrame {
private JFrame frame1, frame2;
public MainWindow() {
super("Main");
//make 2 other frames
frame1 = new Frame1(this);
frame2 = new Frame2(this);
setSize(400, 300);
//add listener to quit if when window closes
addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(WindowEvent arg0) {
System.exit(0);
}
});
//add buttn top open one frame
JButton btnFrame1 = new JButton("Frame 1");
btnFrame1.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
//make frame 1 visible
frame1.setVisible(true);
//make this invisible
setVisible(false);
}
});
getContentPane().add(btnFrame1, BorderLayout.NORTH);
//add button to open a second frame
JButton btnFrame2 = new JButton("Frame 2");
btnFrame2.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
//make frame 1 visible
frame2.setVisible(true);
//make this invisible
setVisible(false);
}
});
getContentPane().add(btnFrame2, BorderLayout.SOUTH);
//make main frame visible
setVisible(true);
}
public static void main(String[] args) {
new MainWindow();
}
public void showMain() {
//make this one invisible
frame1.setVisible(false);
frame2.setVisible(false);
//make main window visible
setVisible(true);
}
}
class Frame1 extends JFrame {
public Frame1(MainWindow mainWindow) {
super("Frame 1");
setSize(300, 200);
//add listener to show main this window closes
addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(WindowEvent arg0) {
mainWindow.showMain();
}
});
//add btn to hide this window and show main
JButton btnFrame1 = new JButton("Back");
btnFrame1.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
mainWindow.showMain();
}
});
getContentPane().add(btnFrame1, BorderLayout.SOUTH);
getContentPane().setBackground(Color.CYAN);
//make it invisible
setVisible(false);
}
}
class Frame2 extends JFrame {
public Frame2(MainWindow mainWindow) {
super("Frame 2");
setSize(300, 200);
//add listener to show main this window closes
addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(WindowEvent arg0) {
mainWindow.showMain();
}
});
JButton btnFrame1 = new JButton("Back");
btnFrame1.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
mainWindow.showMain();
}
});
//add btn to hide this window and show main
JButton btnMain = new JButton("Back");
btnMain.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
mainWindow.showMain();
}
});
getContentPane().add(btnMain, BorderLayout.SOUTH);
getContentPane().setBackground(Color.YELLOW);
//make it invisible
setVisible(false);
}
}
Don't hesitate to ask for clarifications as needed.
when I use updateComponentTreeUI for a non-empty JTextField, the position of the cursor is moved from the end of the text to the front, as seen in the given example. Can anybody think of a reason, a fix, or has experienced this? Since I have many textfields in many different classes, a global solution without adding a Listener to every textfield would be appreciated. Here is a simple example:
import java.awt.*;
import java.awt.Dialog.*;
import java.awt.event.*;
import java.lang.reflect.*;
import javax.swing.*;
public class DialogTest {
final JFrame frame = new JFrame("DialogTest");
JDialog dlg;
public DialogTest() {
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new JButton(action1), BorderLayout.NORTH);
frame.add(new JButton(action2), BorderLayout.CENTER);
frame.pack();
frame.setLocation(200, 200);
frame.setVisible(true);
}
public static void main(String[] args) {
try {
SwingUtilities.invokeAndWait(new Runnable() {
#Override
public void run() {
new DialogTest();
}
});
} catch (InvocationTargetException | InterruptedException e1) {
}
}
private void setStuff() {
dlg = new JDialog(frame, "Dialog", ModalityType.DOCUMENT_MODAL);
dlg.getContentPane().setLayout(new BorderLayout());
dlg.getContentPane().add(new JTextField("test 123", 20), BorderLayout.NORTH);
dlg.getContentPane().add(new JTextField("Bla bla bla bla bla", 20), BorderLayout.CENTER);
dlg.getContentPane().add(new JButton(new AbstractAction("Close") {
#Override
public void actionPerformed(ActionEvent e) {
dlg.setVisible(false);
}
}), BorderLayout.SOUTH);
dlg.setLocation(250, 250);
}
final Action action1 = new AbstractAction("Dialog") {
#Override
public void actionPerformed(ActionEvent e) {
setStuff();
dlg.pack();
dlg.setVisible(true);
}
};
final Action action2 = new AbstractAction("UpdateComponentTree") {
#Override
public void actionPerformed(ActionEvent e) {
setStuff();
SwingUtilities.updateComponentTreeUI(dlg);
dlg.pack();
dlg.setVisible(true);
}
};
}
public final class UserPage extends JFrame{
public UserPage() {
this.addKeyListener(new myclass());
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setSize(1000, 600);
this.setLocation(300, 60);
this.setResizable(false);
this.setVisible(true);
}
.
.
.
public class myclass extends KeyAdapter{
#Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_DELETE) {
System.out.println("Key \"Delete\" Pressed");
}
}
}
}
But, when i press delete button, not see the "Key \"Delete\" Pressed" message!
JFrame (all Top-Level Containers) by default never to react to KeyEvents, have to use this Listener for JComponent they are to consume Focus, or is possible to flag it with setFocusable()
don't to use low_level KeyListener for Swing JComponents, if is possible then to use hight level abstraction, to use KeyBindings instead
JRootPane + KeyBindings(As #mKorbel has already said)
String KEY = "UserPageAction";
f.getRootPane().getActionMap().put(KEY, action);
InputMap im = f.getRootPane().getInputMap();
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0), KEY);
Also check out: JMenuItem#setAccelerator(...)
JMenuItem item = new JMenuItem(action);
item.setAccelerator(KeyStroke.getKeyStroke(
KeyEvent.VK_DELETE, InputEvent.CTRL_DOWN_MASK));
SSCCE
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class UserPageTest {
public static JMenuBar makeMenuBar() {
JMenuBar bar = new JMenuBar();
JMenu menu = new JMenu("Test");
JMenuItem item = new JMenuItem(action);
item.setAccelerator(KeyStroke.getKeyStroke(
KeyEvent.VK_DELETE, InputEvent.CTRL_DOWN_MASK));
menu.add(item);
bar.add(menu);
return bar;
}
public static Action action = new AbstractAction("UserPage?") {
#Override public void actionPerformed(ActionEvent e) {
System.out.println("UserPage Action");
}
};
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override public void run() { createAndShowGUI(); }
});
}
public static void createAndShowGUI() {
JFrame f = new JFrame();
String KEY = "UserPageAction";
f.getRootPane().getActionMap().put(KEY, action);
InputMap im = f.getRootPane().getInputMap();
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0), KEY);
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
f.setJMenuBar(makeMenuBar());
f.setSize(320, 240);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
}
How do I invoke extra operations when the user closes a JFrame window? I have to stop existing threads.
As I understand it, setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); causes the frame to be closed and its thread to be stopped. Should threads be closed after JFrame.EXIT_ON_CLOSE?
Client:
static boolean TERMINATE = false;
public static void main(String[] args) {
// some threads created
while(true) {
if(TERMINATE){
// do before frame closed
break;
}
}
}
private static JPanel startGUI(){
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel gui = new JPanel();
f.add( gui);
f.setSize(500,500);
f.setVisible(true);
return gui;
}
I need to close sockets the thread's working with. What is the best practice to do that?
Using JFrame.EXIT_ON_CLOSE actually terminates the JVM (System.exit). All running threads will automatically be stopped.
If you want to perform some action when a JFrame is about to close, use a WindowListener.
JFrame frame = ...
frame.addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(WindowEvent e) {
// close sockets, etc
}
});
You have to add a WindowListener to the JFrame.
Inside the windowClosing method, you can provide required code.
For example:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class ClosingFrame extends JFrame {
private JMenuBar MenuBar = new JMenuBar();
private JFrame frame = new JFrame();
private static final long serialVersionUID = 1L;
private JMenu File = new JMenu("File");
private JMenuItem Exit = new JMenuItem("Exit");
public ClosingFrame() {
File.add(Exit);
MenuBar.add(File);
Exit.addActionListener(new ExitListener());
WindowListener exitListener = new WindowAdapter() {
#Override
public void windowClosing(WindowEvent e) {
int confirm = JOptionPane.showOptionDialog(frame,
"Are You Sure to Close this Application?",
"Exit Confirmation", JOptionPane.YES_NO_OPTION,
JOptionPane.QUESTION_MESSAGE, null, null, null);
if (confirm == 0) {
System.exit(1);
}
}
};
frame.addWindowListener(exitListener);
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
frame.setJMenuBar(MenuBar);
frame.setPreferredSize(new Dimension(400, 300));
frame.setLocation(100, 100);
frame.pack();
frame.setVisible(true);
}
private class ExitListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
int confirm = JOptionPane.showOptionDialog(frame,
"Are You Sure to Close this Application?",
"Exit Confirmation", JOptionPane.YES_NO_OPTION,
JOptionPane.QUESTION_MESSAGE, null, null, null);
if (confirm == 0) {
System.exit(1);
}
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
ClosingFrame cf = new ClosingFrame();
}
});
}
}
You can set the default close operation on the JFrame
JFrame frame = new JFrame("My Frame");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
What is a good way to dispose of a JFrame with code like this? I want to handle the Window exit and window close.
I know we shouldn't use System.exit();
public class JavaCellularAutomataSquare {
public static final String TITLE = "Cellular Automata - Squaring Example";
private int maxWidth = 600;
private int maxHeight = 600;
public void launch() {
final JFrame frame = new JFrame(TITLE);
frame.setLocation(20, 20);
frame.setPreferredSize(new Dimension(maxWidth, maxHeight));
frame.setResizable(false);
frame.setFocusable(true);
final JPanel panel = new JPanel();
panel.setLocation(20, 20);
panel.setVisible(true);
panel.setPreferredSize(new Dimension(maxWidth, maxHeight));
panel.setFocusable(true);
panel.setBackground(Color.white);
// Panel setup, toggle visibility on frame
frame.add(panel);
frame.pack();
frame.setVisible(true);
}
}
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class ClosingFrame extends JFrame {
private JMenuBar MenuBar = new JMenuBar();
private JFrame frame = new JFrame();
private static final long serialVersionUID = 1L;
private JMenu File = new JMenu("File");
private JMenuItem Exit = new JMenuItem("Exit");
public ClosingFrame() {
File.add(Exit);
MenuBar.add(File);
Exit.addActionListener(new ExitListener());
WindowListener exitListener = new WindowAdapter() {
#Override
public void windowClosing(WindowEvent e) {
int confirm = JOptionPane.showOptionDialog(frame,
"Are You Sure to Close this Application?",
"Exit Confirmation", JOptionPane.YES_NO_OPTION,
JOptionPane.QUESTION_MESSAGE, null, null, null);
if (confirm == JOptionPane.YES_OPTION) {
System.exit(0);
}
}
};
frame.addWindowListener(exitListener);
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
frame.setJMenuBar(MenuBar);
frame.setPreferredSize(new Dimension(400, 300));
frame.setLocation(100, 100);
frame.pack();
frame.setVisible(true);
}
private class ExitListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
int confirm = JOptionPane.showOptionDialog(frame,
"Are You Sure to Close this Application?",
"Exit Confirmation", JOptionPane.YES_NO_OPTION,
JOptionPane.QUESTION_MESSAGE, null, null, null);
if (confirm == JOptionPane.YES_OPTION) {
System.exit(0);
}
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
ClosingFrame cf = new ClosingFrame();
}
});
}
}
JFrame.setDefaultCloseOperation(DISPOSE_ON_CLOSE) frees up resources when the window is closed. You can see some of the other operations in the Java tutorials here.
The possible arguments that you can use in the method are defined in the WindowConstants interface, if you are curious about your options.
If you need to perform some operations while closing your application, propably you need a
shut down hook. Have a look at this post.
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JFrame.setDefaultCloseOperation(int operation)
JFrame.EXIT_ON_CLOSE