I was wondering if there is a way, by clicking on the "X", to let the program perform some code before closing the JFrame. The setDefaultCloseOperation() method takes only an integer.
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent e){
int i=JOptionPane.showConfirmDialog(null, "Seguro que quiere salir?");
if(i==0)
System.exit(0);//cierra aplicacion
}
});
#Jeffrey has a good answer, but you should consider what you're trying to do. If you really want to do something upon the closing of a frame, then a WindowListener is the way to go. However, if you're looking for a place to do some cleanup and graceful shutdown stuff, then you probably want a shutdown hook instead. Using a WindowListener, the code will only be triggered, as you said, by the user "clicking on the X". But what if the user starts the app in the foreground of a terminal and kills it with Ctrl+C? What if the user kills the process from the command line or from a task manager?
You might be interested in using a WindowListener. The WindowListener tutorial.
Related
In my program, I need to wait for the user to input from a JFrame. When the user is done with the first input they press a JButton. This calls a constructor for a Class I made: HumanTrainer. In the constructor I need the user to have more inputs. I made two functions to wait and notify. But when the code gets to wait, everything freezes, and the JFrame doesn't update to what it should.
This is the action the first button preforms
startingButton.addActionListener((e)->{
Trainer[]t=new Trainer[2];//HumanTrainer extends Trainer
String[]names=new String[2];
for(int a=0;a<2;a++)
names[a]=((JTextField)(startingInputs[2][1+a])).getText();
grid.removeAll();//The JPanel that the Frame has
Frame.repaint();//The JFrame
Frame.validate();
if(isHuman[0])
t[0]=new HumanTrainer(names[0],grid,Frame);//The constructor
if(isHuman[1])
t[1]=new HumanTrainer(names[1],grid,Frame);
});
And the constructor for HumanTrainer
HumanTrainer(String name,JPanel grid,JFrame Frame){
super(name);
GridBagConstraints manager=new GridBagConstraints();
manager.gridx=0;
manager.gridy=0;
manager.gridheight=1;
manager.gridwidth=1;
manager.fill=GridBagConstraints.HORIZONTAL;
Font Format=new Font("Courier New",Font.PLAIN,14);
JButton cont=new JButton("Continue");//This is the button that when clicked should run the function that notifies
grid.add(cont,manager);
grid.repaint();//One of these four things SHOULD change the view of the frame
grid.validate();
Frame.repaint();
Frame.validate();
System.out.print("TEST");//This prints
cont.addActionListener((e)->{
made();//This is a function contained in HumanTrainer that only calls notify();
});
make();//This is a function contained in HumanTrainer that only calls wait(); With the proper try and catch
}
But when starterButton is pressed the screen freezes and doesn't update so that cont can be pressed.
Start by taking a look at Concurrency in Swing. Swing uses a single thread to dispatch it's events from, if you perform any long running or blocking operation from within the EDT (like calling wait), then it freeze your program and the user will have to terminate it.
You have two basic choices. You can either use a modal dialog to gather information from the user, see How to Make Dialogs, which will block the execution of the code at the point they are displayed, without blocking the entire EDT OR use a observer pattern, which can generate notifications that the user has provided what ever information you are expecting.
To be honest, a modal dialog is generally easier and can help prevent unexpected side effects
This...
make();//This is a function contained in HumanTrainer that only calls wait(); With the proper try and catch
would seem to be the core of your problem, but without more information and context of what you are trying to do, it's impossible to really suggest what you should do, however I'd recommend having a look at model-view-controller and seperare your code into more appropriate layers
First of all, you may want to close that for loop with {} so that it doesn't loop the whole code twice. Also you should check if wait() and notify() work correctly by individually testing them without java awt.
Is there a way to add/override the action event of THIS button ? I couldn't find anywhere how to acces this button and override it's action. In my case I need to do this because I need to save the resources before I exit my window, and if I press the x button, It will exit automatically.
On the JFrame:
setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
Then add a WindowsListener and in the windowClosing(WindowEvent event) methods do your job and then call dispose()
I'd use a shut-down hook instead that way it'll save even if you close the app via another method.
Looky here
You can try using a WindowListener interface. If I remember correctly, it should allow you to do things when something on the frame is clicked on(like exiting).
See http://docs.oracle.com/javase/6/docs/api/java/awt/event/WindowListener.html
Good day!
I'm developping a small Java Application with NetBeans IDE that extends JFrame. I implemented several ways to close the App, for example pressing Ctrl-Q and pressing the X of the JFrame.
But before the actual closing I'd like the program to execute some additional code for me, to save some objects the application needs to reuse the next time it starts up.
What is the best way to change the entire programs closing behavior?
I'm thinking about overriding/replacing the defaultCloseOperation, something like this:
setDefaultCloseOperation( myOwnCloseOperation );
Thanks for any help!
setDefaultCloseOperation( JFrame.DO_NOTHING_ON_CLOSE )
Add a WindowListener or WindowAdapter - overriding either the windowClosing() or windowClosed() methods (I forget which) to catch the closing event.
Call the save functionality from the window method.
Call setVisible(false) or dispose() (as discussed in the comments) at the end.
I would like to make possible the navigation of frames in java.Whenever i close a frame the remaining frames which are also opened get closed;and the entire program stops.
Please help...
You probably used
//this will terminate or exit your application
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Maybe you want to use this instead,
setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
for your reference go to this link
If you want to close only that one frame, you should do something like this: setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE)
If you want to close all frames whenever a single frame closes you can do the following:
You could use a window listener and call System.exit(0); when the JFrame closes, or try setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); on each JFrame. That way your program would close all frames and end.
If you need to perform some tasks before application quits, you should probably use the window listener.
You can also do that graphicaly. right click on your frame and select properties and from there you can change that like the below picture.
If you were using swing palette. In frame properties choose default close operation as (Dispose). Follow as per the image given in this solution.
My problem was that I used a listener found on the basic tutorials :
WindowListener l = new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
};
addWindowListener(l);
I know it's dumb. I didn't see it, but some people might have done the same thing, so I'll just leave this here ;)
I added an window state listener as follow:
this.addWindowStateListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
ExitAction.getInstance().actionPerformed(null);
}
});
But when I'm using the X close button the event is not called.
I think it's something to do with netbean jdesktop framework. But I can't find what could be the problem.
Thanks for your help.
windowClosing is part of the WindowListener interface. Use addWindowListener instead of addWindowStateListener.
Normally you use a WindowListener for this.
Check out Closing an Application for an approach I use, although I must admit I've never tried it with Netbeans since I don't use an IDE.
Not answering your question directly (since an answer has already been given), but I assume you want to quit your program (or just hide a window) on exit. There is a shorter solution for these situations:
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Just debugged a similar problem in my Swing program. It turned out to be a Java bug that kills the system UI events when ImageIO is called before the Swing UI is created. See here for a minimal example -
https://stackoverflow.com/questions/18964138/osx-specific-new-java-ui-bug-reproducable-java-imageio-close-window-event-bug
This bug stops the system UI events, such as window-close, from being delivered to Java.
As the Java documentation says, to actually close the window the listener should invoke the window's dispose or setVisible(false) method.
Thank you everyone for helping me solve the problem. I don't fully understend it but the following code solve the problem:
Frame[] frames = Frame.getFrames();
for(Frame f: frames){
f.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
ExitAction.getInstance().actionPerformed(null);
}
});
}
It look as if the framework add additional frames.
Thanks,
As others have pointed out the WindowListener is what you are after... but you should do this from now on when overriding a method:
this.addWindowStateListener(
new WindowAdapter()
{
#Overrides
public void windowClosing(WindowEvent e)
{
ExitAction.getInstance().actionPerformed(null);
}
});
Then the compiler will tell you when you are not actually overriding a method and are instead adding a new method (that in this case will never be called).