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);
Related
I have the following problem:
I have a main application window (JFrame) that fills the whole screen.
When a button is clicked, a smaller window appears, to let the user input some Data. While the User does this, the main window should neither jump in front of it, nor allow interaction.
Solution to that: open a modal JDialog. Lets call that Dialog 1.
But when a button within this Dialog is clicked, a NEW window (yes/no-dialog) is supposed to pop up.. and, again, needs to act modal on the already modal JDialog Dialog 1. Trying to do that, the second Dialog keeps disappearing behind the first one.
I tried making Dialog 1 a JFrame but then, of course, I loose the "modal" bit. Forcing Dialog 1 to stay in from still keeps the main window's Button clickable.
What am I missing? How can I put a modal swing window OVER another modal swing window?
Edit:
minimal example of one not-really working version:
Main class for opening:
public class MainWin extends JFrame {
public MainWin(){
this.setSize(800,800);
JButton b = new JButton("click hehe");
this.getContentPane().add(b);
b.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
new Dia1(MainWin.this);
}
});
this.setVisible(true);
}
}
Main window:
public class MainWin extends JFrame {
public MainWin(){
this.setSize(800,800);
JButton b = new JButton("click hehe");
this.getContentPane().add(b);
b.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
new Dia1(MainWin.this);
}
});
this.setVisible(true);
}
}
First Dialog:
public class Dia1 extends JDialog {
public Dia1(final JFrame parent){
super(parent, true);
this.setSize(400, 400);
JButton b = new JButton("click hehe");
this.getContentPane().add(b);
this.setVisible(true);
b.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
new Dia2(parent);
}
});
}
}
Second Dialog:
public class Dia2 extends JDialog {
public Dia2(JFrame parent){
super(parent, true);
this.setSize(200, 200);
JButton b = new JButton("click hehe");
this.getContentPane().add(b);
this.setVisible(true);
}
}
PS: I just realised: Dialog 2 is not hidden, as I suspected.. it is simply not there. Most likely because the parent window is blocked from the Modal Dialog?
Here is an MCVE of modality working as advertised.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
public class ModalOverModal {
private JComponent ui = null;
ModalOverModal() {
initUI();
}
public void initUI() {
if (ui!=null) return;
ui = new JPanel(new GridLayout());
ui.setBorder(new EmptyBorder(40,40,40,40));
final JButton b1 = new JButton("Open Modal Dialog");
b1.setMargin(new Insets(40, 200, 40, 200));
ui.add(b1);
final JButton b2 = new JButton("Open 2nd Modal Dialog");
ActionListener al1 = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(b1, b2);
}
};
b1.addActionListener(al1);
ActionListener al2 = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(b2, "Close Me!");
}
};
b2.addActionListener(al2);
}
public JComponent getUI() {
return ui;
}
public static void main(String[] args) {
Runnable r = new Runnable() {
#Override
public void run() {
ModalOverModal o = new ModalOverModal();
JFrame f = new JFrame("Modal over Modal");
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
f.setLocationByPlatform(true);
f.setContentPane(o.getUI());
f.pack();
f.setMinimumSize(f.getSize());
f.setVisible(true);
}
};
SwingUtilities.invokeLater(r);
}
}
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();
}
});
}
}
I have a JFrame that I want closed when the user clicks off of it. I have two JTextFields and a JButton (username, password, submit). When I give them all the FocusListener, anytime the user goes from one field to another the window closes. How can I allow the user to go from field to field and only close it if the user clicks anywhere OUT of the pop up window?
public class LoginForm {
static JTextField userName;
static JTextField password;
static JButton submit;
JFrame main;
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
UserSession session;
public LoginForm(){
Handler handle = new Handler(); //inner class
LoginFormFocusListener fl = new LoginFormFocusListener(); //inner class
main = new JFrame("Please Login");
main.setUndecorated(true);
main.setBounds((dim.width/2) - (500/2),(dim.height/2) - (150/2),500,150);
main.setVisible(true);
main.setAlwaysOnTop(true);
main.setResizable(false);
main.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
userName = new JTextField(10);
password = new JTextField(10);
main.setLayout(new GridLayout(0,1));
JPanel panel = new JPanel();
main.add(panel);
panel.add(new JLabel("Username: "));
panel.add(userName);
panel.add(new JLabel("Password: "));
panel.add(password);
submit = new JButton("Submit");
panel.add(submit);
userName.addFocusListener(fl);
password.addFocusListener(fl);
submit.addFocusListener(fl);
submit.addActionListener(handle);
}
}
... (unimportant methods and "Handler" class omitted)
public class LoginFormFocusListener implements FocusListener{
public void focusGained(FocusEvent fe) {
System.out.println("focus gained...");
System.out.println("click off of this window to close...");
}
public void focusLost(FocusEvent fe){
System.out.println("focus lost...");
WindowEvent winEvt = new WindowEvent(main, 0);
winEvt.getWindow().dispose();
}
}
//test
public static void main(String args[]){
SwingUtilities.invokeLater(new Runnable(){
public void run(){
new LoginForm();
}
});
}
Don't use a FocusListener for this since these are for components that gain and lose the focus, not for top level windows. Perhaps use a WindowListener listening for the window is deactivated or iconified.
For example:
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class WindowListenerFun {
public static void main(String[] args) {
JPanel panel = new JPanel();
panel.add(new JTextField(10));
panel.add(new JButton("button"));
JFrame frame = new JFrame("Bad Frame");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(panel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
frame.addWindowListener(new WindowAdapter() {
#Override
public void windowIconified(WindowEvent wEvt) {
((JFrame)wEvt.getSource()).dispose();
}
#Override
public void windowDeactivated(WindowEvent wEvt) {
((JFrame)wEvt.getSource()).dispose();
}
});
}
}
EDIT: I misread your code; the other answer is correct--you need to use a WindowFocusListener instead of a FocusListener.
public class Listener extends WindowAdapter
{
public void windowLostFocus(WindowEvent e)
{
Window w = e.getWindow();
e.setVisible(false);
e.dispose();
}
}
and
main.addWindowFocusListener(new Listener());
Edit2: replaced placeholder with window closing code.
Then you add a focus listener to individual menu components, it gets fired whenever a component loses focus. You only want it to get fired when the window loses focus, so add it to the window instead.
main.addWindowFocusListener(f1);
should fix your problem.
I have a button in a java frame that when pressed it reads a value from a text field and uses that string as a port name attempting to connect to a serial device.
If this connection is successful the method returns true if not it returns false. If it returns true I want the frame to disappear. A series of other frames specifed in other classes will then appear with options to control the serial device.
My problem is: the button is connected to an action listener, when pressed this method is invoked. If I try to use the frame.setVisible(true); method java throws a abstract button error because I'm effectively telling it to disappear the frame containing the button before the button press method has exited. Removing the frame.setVisible(true); allow the program to run correctly however I am left with a lingering connection frame that is no longer any use.
How to I get the frame to disappear upon pressing a the button?
package newimplementation1;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
/**
*
* #author Zac
*/
public class ConnectionFrame extends JPanel implements ActionListener {
private JTextField textField;
private JFrame frame;
private JButton connectButton;
private final static String newline = "\n";
public ConnectionFrame(){
super(new GridBagLayout());
textField = new JTextField(14);
textField.addActionListener(this);
textField.setText("/dev/ttyUSB0");
connectButton = new JButton("Connect");
//Add Components to this panel.
GridBagConstraints c = new GridBagConstraints();
c.gridwidth = GridBagConstraints.REMAINDER;
c.fill = GridBagConstraints.HORIZONTAL;
add(textField, c);
c.fill = GridBagConstraints.BOTH;
c.weightx = 1.0;
c.weighty = 1.0;
add(connectButton, c);
connectButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
boolean success = Main.mySerialTest.initialize(textField.getText());
if (success == false) {System.out.println("Could not connect"); return;}
frame.setVisible(false); // THIS DOES NOT WORK!!
JTextInputArea myInputArea = new JTextInputArea();
myInputArea.createAndShowGUI();
System.out.println("Connected");
}
});
}
public void actionPerformed(ActionEvent evt) {
// Unimplemented required for JPanel
}
public void createAndShowGUI() {
//Create and set up the window.
frame = new JFrame("Serial Port Query");
frame.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
//Add contents to the window.
frame.add(new ConnectionFrame());
frame.setLocation(300, 0);
//Display the window.
frame.pack();
frame.setVisible(true);
frame.addComponentListener(new ComponentAdapter() {
#Override
public void componentHidden(ComponentEvent e) {
System.out.println("Exiting Gracefully");
Main.mySerialTest.close();
((JFrame)(e.getComponent())).dispose();
System.exit(0);
}
});
}
}
Running your snippet (after removing/tweaking around the custom classes), throws an NPE. Reason is that the frame you'r accessing is null. And that's because it's never set. Better not rely on any field, let the button find its toplevel ancestor and hide that, like in
public void actionPerformed(final ActionEvent e) {
boolean success = true;
if (success == false) {
System.out.println("Could not connect");
return;
}
Window frame = SwingUtilities.windowForComponent((Component) e
.getSource());
frame.setVisible(false); //no problem :-)
}
Your problem is with this line:
frame.add(new ConnectionFrame());
You're creating a new ConnectionFrame object, and so the frame that your button tries to close on is not the same as the one being displayed, and this is the source of your problem.
If you change it to,
//!! frame.add(new ConnectionFrame());
frame.add(this);
so that the two JFrames are one and the same, things may work more smoothly.
But having said that, your whole design smells bad and I'd rethink it in a more OOP and less static fashion. Also, use dialogs where dialogs are needed, not frames, and rather than dialogs consider swapping views (JPanels) via CardLayout as a better option still.
Myself, I'd create a "dumb" GUI for this, one that creates a JPanel (here in my example it extends a JPanel for simplicity, but I'd avoid extending if not necessary), and I'd let whoever is calling this code decide what to do with the information via some control. For e.g.,
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
#SuppressWarnings("serial")
public class ConnectionPanel extends JPanel {
private JTextField textField;
private JButton connectButton;
private ConnectionPanelControl control;
public ConnectionPanel(final ConnectionPanelControl control) {
super(new GridBagLayout());
this.control = control;
ActionListener listener = new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (control != null) {
control.connectButtonAction();
}
}
};
textField = new JTextField(14);
textField.addActionListener(listener);
textField.setText("/dev/ttyUSB0");
connectButton = new JButton("Connect");
GridBagConstraints c = new GridBagConstraints();
c.gridwidth = GridBagConstraints.REMAINDER;
c.fill = GridBagConstraints.HORIZONTAL;
add(textField, c);
c.fill = GridBagConstraints.BOTH;
c.weightx = 1.0;
c.weighty = 1.0;
add(connectButton, c);
connectButton.addActionListener(listener);
}
public String getFieldText() {
return textField.getText();
}
}
Again, something outside of the simple GUI would make decisions on what to do with the text that the textfield contains and what to do with the GUI that is displaying this JPanel:
public interface ConnectionPanelControl {
void connectButtonAction();
}
Also, you will likely do any connecting in a background thread so as to not freeze your GUI, probably a SwingWorker. Perhaps something like this:
import java.awt.event.ActionEvent;
import java.util.concurrent.ExecutionException;
import javax.swing.*;
#SuppressWarnings("serial")
public class MyMain extends JPanel {
public MyMain() {
add(new JButton(new ConnectionAction("Connect", this)));
}
private static void createAndShowGui() {
JFrame frame = new JFrame("My Main");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new MyMain());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
#SuppressWarnings("serial")
class ConnectionAction extends AbstractAction {
private MyMain myMain;
private ConnectionPanel cPanel = null;
private JDialog dialog = null;
public ConnectionAction(String title, MyMain myMain) {
super(title);
this.myMain = myMain;
}
#Override
public void actionPerformed(ActionEvent e) {
if (dialog == null) {
dialog = new JDialog(SwingUtilities.getWindowAncestor(myMain));
dialog.setTitle("Connect");
dialog.setModal(true);
cPanel = new ConnectionPanel(new ConnectionPanelControl() {
#Override
public void connectButtonAction() {
final String connectStr = cPanel.getFieldText();
new MySwingWorker(connectStr).execute();
}
});
dialog.getContentPane().add(cPanel);
dialog.pack();
dialog.setLocationRelativeTo(null);
}
dialog.setVisible(true);
}
private class MySwingWorker extends SwingWorker<Boolean, Void> {
private String connectStr = "";
public MySwingWorker(String connectStr) {
this.connectStr = connectStr;
}
#Override
protected Boolean doInBackground() throws Exception {
// TODO: make connection and then return a result
// right now making true if any text in the field
if (!connectStr.isEmpty()) {
return true;
}
return false;
}
#Override
protected void done() {
try {
boolean result = get();
if (result) {
System.out.println("connection successful");
dialog.dispose();
} else {
System.out.println("connection not successful");
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
}
Your code would be much more readable if you named JFrame instances xxxFrame, and JPanel instances xxxPanel. Naming JPanel instances xxxFrame makes things very confusing.
It would also help if you pasted the stack trace of the exception.
I suspect the problem comes from the fact that frame is null. This is due to the fact that the frame field is only initialized in the createAndShowGUI method, but this method doesn't display the current connection panel, but a new one, which thus have a null frame field:
ConnectionFrame firstPanel = new ConnectionFrame();
// The firstPanel's frame field is null
firstPanel.createAndShowGUI();
// the firstPanel's frame field is now not null, but
// the above call opens a JFrame containing another, new ConnectionFrame,
// which has a null frame field
The code of createAndShowGUI should contain
frame.add(this);
rather than
frame.add(new ConnectionFrame());
for Swing GUI is better create only once JFrame and another Top-Level Containers would be JDialog or JWindow(un-decorated by default),
simple example here
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class SuperConstructor extends JFrame {
private static final long serialVersionUID = 1L;
public SuperConstructor() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setPreferredSize(new Dimension(300, 300));
setTitle("Super constructor");
Container cp = getContentPane();
JButton b = new JButton("Show dialog");
b.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent evt) {
FirstDialog firstDialog = new FirstDialog(SuperConstructor.this);
}
});
cp.add(b, BorderLayout.SOUTH);
JButton bClose = new JButton("Close");
bClose.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent evt) {
System.exit(0);
}
});
add(bClose, BorderLayout.NORTH);
pack();
setVisible(true);
}
public static void main(String args[]) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
SuperConstructor superConstructor = new SuperConstructor();
}
});
}
private class FirstDialog extends JDialog {
private static final long serialVersionUID = 1L;
FirstDialog(final Frame parent) {
super(parent, "FirstDialog");
setPreferredSize(new Dimension(200, 200));
setLocationRelativeTo(parent);
setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
setModalityType(Dialog.ModalityType.DOCUMENT_MODAL);
JButton bNext = new JButton("Show next dialog");
bNext.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent evt) {
SecondDialog secondDialog = new SecondDialog(parent, false);
}
});
add(bNext, BorderLayout.NORTH);
JButton bClose = new JButton("Close");
bClose.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent evt) {
setVisible(false);
}
});
add(bClose, BorderLayout.SOUTH);
pack();
setVisible(true);
}
}
private int i;
private class SecondDialog extends JDialog {
private static final long serialVersionUID = 1L;
SecondDialog(final Frame parent, boolean modal) {
//super(parent); // Makes this dialog unfocusable as long as FirstDialog is visible
setPreferredSize(new Dimension(200, 200));
setLocation(300, 50);
setModal(modal);
setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
setTitle("SecondDialog " + (i++));
JButton bClose = new JButton("Close");
bClose.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent evt) {
setVisible(false);
}
});
add(bClose, BorderLayout.SOUTH);
pack();
setVisible(true);
}
}
}
better would be re-use Top-Level Containers, as create lots of Top-Level Containers on Runtime (possible memory lack)
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