Programmatic close of JFrame - java

What's the programmatic equivalent of clicking the close (x) button in the upper right corner of a JFrame?
There's the dispose() method but that's not the same thing, since a JFrame can be set to do several different things upon closing (not to mention if there's a WindowListener involved)

You tell the component to dispatch an event. In this case, you want it do dispatch a Window Closing event.
private void exit() {
this.dispatchEvent(new WindowEvent(this, WindowEvent.WINDOW_CLOSING));
}

When you hit the x on a JFrame, the system can be set to do various things. The default is that the window is simply hidden with setVisible(false) I believe.
You can set a frame to do different things on close--you can have it dispose, hide or call code based on setDefaultCloseOperation. Here are the options:
DO_NOTHING_ON_CLOSE: Don't do anything; require the program to handle the operation in the windowClosing method of a registered WindowListener object.
HIDE_ON_CLOSE: Automatically hide the frame after invoking any registered WindowListener objects.
DISPOSE_ON_CLOSE: Automatically hide and dispose the frame after invoking any registered WindowListener objects.
EXIT_ON_CLOSE: Exit the application using the System exit method. Use this only in applications.
But I think what you are after is setVisible(false).

You have to insert the call into the AWT message queue so all the timing happens correctly, otherwise it will not dispatch the correct event sequence, especially in a multi-threaded program.
public void closeWindow()
{
if(awtWindow_ != null) {
EventQueue.invokeLater(new Runnable() {
public void run() {
awtWindow_.dispatchEvent(new WindowEvent(awtWindow_, WindowEvent.WINDOW_CLOSING));
}
});
}
}

Related

Java requestFocus() not working at the constructor

In my Java Swing Application Reuestfocus method not working at the Constructor. But it works if I used requestfocus along with button action listener. I want set Requestfocus at the form load. I dont understand whats the wrong here. P.S I use JInternal Frame
txtItemName.requestFocusInWindow (); // did not work
txtItemName.requestFocus (); // did not work
public ItemMgt() {
initComponents();
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
txtItemName.requestFocus(); // did not work
}
});
}
private void formInternalFrameActivated(javax.swing.event.InternalFrameEvent evt) {
txtItemName.requestFocus(); // did not work.
}
The case might by that your component is not visible, so the GUI manager can not set focus on it.
As is specified in documentation:
(..) component must be displayable, focusable, visible and all of its ancestors (with the exception of the top-level Window) must be visible for the request to be granted.
Generally you should avoid to have so robust logic in constructor. Your graphic components should be constructed first. When this is finished they should be adjusted to your preferences.
Instead of requestFocus(), it is recomended to use requestFocusInWindow() for more please visit the tutorial: How to Use the Focus Subsystem
If you are using Netbeans IDE, then its much easier. Just make sure that all controls before your textbox are not focusable by unchecking the 'focusable' property in the Properties window. This will leave your textbox as the first focusable control thus allowing it to receive focus when the internal frame is opened

Can I add a WindowListener to a MenuItem?

I have a program written in AWT, so I am using Frame (Not JFrame/Swing).
I am using MenuItem objects to do some operations through ActionListeners.
However, on my last MenuItem, I want to use a WindowListener to close the frame (intending to close the frame without terminating the program altogether).
I am aware that the MenuItem documentation doesn't have a addWindowListener() method. But is there a way around that?
f.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
f.dispose();
}});
This is pretty much what I'm trying to do, but from a MenuItem.
The window listener is not about making the window close - it's a set of callbacks that happen when a window does particular things. From the Javadoc:
When the window's status changes by virtue of being opened, closed, activated or deactivated, iconified or deiconified, the relevant method in the listener object is invoked, and the WindowEvent is passed to it.
windowClosing has the following Javadoc:
void windowClosing(WindowEvent e)
Invoked when the user attempts to close the window from the window's system menu.
If you want to programatically close the window when someone clicks the menu item, then simply add an action listener with the following:
f.setVisible(false);
f.dispose();

Closing a java program properly when JDialog is the main window

I have a JDialog as the main window in my application (originally it was a JFrame but it showed in the taskbar which I didn't want).
Currently I am doing:
setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
and when I click an exit button:
frame.dispose();
But the process still seems to hang around in the background
JFrame had JFrame.EXIT_ON_CLOSE which seemed to do what I wanted.
How can I close my application properly?
You need to add a WindowListener that will do System.exit(0) when the dialog closes.
JDialog dialog = ...;
dialog.addWindowListener(new WindowAdapter() {
#Override public void windowClosed(WindowEvent e) {
System.exit(0);
}
});
Of course, the System.exit(0) after you hit the Exit button (that was suggested elsewhere in this thread) is still needed.
You can add
System.exit(0);
where you want the program to end, maybe immediately after the dispose() line.
consider using JWindow(un-decoretad by defalut), but that's little bit complicating fact, that JWindow required initializations from JFrame (just must exist, nothing else) as parent
better would be add WindowListener and all Events/Actions would be redirected/managed this way
You know that the EXIT_ON_CLOSE field is also inherited by JDialog, right?
As mentioned by #camickr, EXIT_ON_CLOSE is not a valid value for the setDefaultCloseOperation method of the JDialog class. As stated by the API,
Sets the operation that will happen by default when the user initiates
a "close" on this dialog. You must specify one of the following
choices:
DO_NOTHING_ON_CLOSE (defined in WindowConstants): Don't do anything; require the program to handle the operation in the
windowClosing method of a registered WindowListener object.
HIDE_ON_CLOSE (defined in WindowConstants): Automatically hide the dialog after invoking any registered WindowListener objects.
DISPOSE_ON_CLOSE (defined in WindowConstants): Automatically hide and dispose the dialog after invoking any registered WindowListener objects.
If EXIT_ON_CLOSE is passed as an argument, an IllegalArgumentException will be thrown.
For me worked only with windowClosing event:
dialog.addWindowListener(new WindowAdapter()
#Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
you can try this below amazing source code -
JDialog dialog = (JDialog) container;
dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
dialog.setModal(false);
dialog.setVisible(false);
dialog.dispose();
Runtime.getRuntime().exit(1);
this above said will shut off the process as well as after disposing the JDialog container, also one more benefit is there, if this JDialog is running above any other JFrame or JDialog, so the parent will not terminate but if this JDialog is running on its own, then the process will get terminated completely, Enjoy.

What is the correct way of manipulating Swing components at program startup?

I'm creating an application in Swing using NetBeans. I would like to be able to manipulate some components during its startup (just once), after the window's made visible, for example update a progress bar. To this end, I have the app's main class, called MainWindow:
public class MainWindow extends JFrame
{
public MainWindow()
{
initComponents(); // NetBeans GUI builder-generated function for setting
// up the window components
}
public void Init()
{
loadLabel.setText("Loading....");
loadProgressBar.setValue(20);
doSomething();
loadProgressBar.setValue(40);
doSomething();
loadProgressBar.setValue(80);
doSomething();
loadProgressBar.setValue(100);
loadLabel.setVisible(false);
loadProgressBar.setVisible(false);
}
/* .... */
public static void main(String args[])
{
java.awt.EventQueue.invokeLater(new Runnable()
{
public void run()
{
mainHandle = new MainWindow();
mainHandle.setVisible(true);
mainHandle.Init();
}
});
}
}
The problem is that the effect of the statements for updating the progress bar (or manipulating any other GUI component) within the Init() function can't be observed. If the Init() function is called from within main() as shown above, the window appears, but is empty, the Init() function executes and returns, only afterwards the window draws its contents but any changes made by Init() aren't visible because the window was empty and inactive the whole time. I also tried calling init from the windowOpened() AWT event, which executes after the window is fully drawn, but amazingly putting any statements for manipulating components there seems to have no effect, or rather they are put in a queue, and executed rapidly at some point in succession, so only the effect of the last one (hiding of the elements) can be observed. The only way I managed to get it working was to remove the whole invokeLater(new Runnable()...) mantra and put the new MainWindow(), setVisible(), Init() sequence directly in main(), which I guess is very ugly and breaks the concept of the gui running in a threaded manner. What is the right way to do this? Where do I put code to be executed first thing when the gui is ready to be manipulated, execute the statements once and return control to the main event loop?
I guess at the moment this is working in such a way, that while the Init() function is operating, any operations on the gui components are suspended (the drawing thread isn't separate and waits for Init() to finish before the manipulations are executed). Maybe I should make Init() a new thread... only how and what kind?
Thanks.
You could change the EventQueue.invokeLater() to invokeAndWait(), and move the call to init() out to a second EventQueue.invokeLater() call.
If (as looks to be the case) doSomething() takes a noticable amount of time, a better idea is to move the Init code into the body of a SwingWorker. This could be executed from the MainWindow() constructor or after the setVisible() call in main and is the idiomatic way to have a responsive GUI (in case the user gets bored waiting and wants to quit) and display some visible signs of progress.
See the process and publish methods for details on how to update the progress bar between doSomething() calls.
You may also want to look into ProgressMonitors for another alternative that would deal with the dialog box etc for you.
There are several things you can do:
For windows (such as JFrame or JDialog) you can attach WindowListener and do your manipulations in windowOpened method.
Override addNotify method and do your control manipulations there.
Attach HierarchyListener and do your manipulations whenever displayability of component changed.
Always make sure your do your component manipulations on EDT. Use SwingUtilities.invokeLater for simple UI updates or SwingWorker for long running tasks

Why does my application still run after closing main window?

If I make a JFrame like this
public static void main(String[] args) {
new JFrame().setVisible(true);
}
then after closing the window the appication doesn't stop (I need to kill it).
What is the proper way of showing application's main windows ?
I'd also like to know a reason of a proposed solution.
Thanks in advance.
You should call the setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); in your JFrame.
Example code:
public static void main(String[] args) {
Runnable guiCreator = new Runnable() {
public void run() {
JFrame fenster = new JFrame("Hallo Welt mit Swing");
fenster.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
fenster.setVisible(true);
}
};
SwingUtilities.invokeLater(guiCreator);
}
There's a difference between the application window and the application itself... The window runs in its own thread, and finishing main() will not end the application if other threads are still active. When closing the window you should also make sure to close the application, possibly by calling System.exit(0);
Yuval =8-)
You must dispose the frame, invoking the dispose method in your window listener or using setDefaultCloseOperation. For the argument of the last one, you can use two options:
DISPOSE_ON_CLOSE or EXIT_ON_CLOSE.
DISPOSE_ON_CLOSE only dispose the frame resources.
EXIT_ON_CLOSE disposes the frame resources and then invokes System.exit.
There is no real difference between the two unless you have non daemon threads.
I prefer to use DISPOSE_ON_CLOSE because this way I'm able to notice if I forgot to terminate a thread, because the JVM will stop if there are no more threads running. That's also the reason closing a Frame without disposing will not terminate the application, since Swing creates a thread to handle events that is terminated only when dispose is invoked.
The correct way to do this (unless you're writing a very trivial single-window app, i.e. no other windows or threads etc..) is to catch the windowClosing() event, and then call the dispose(); method of the form.
If your program doesn't completely exit after this, it means you have other non-deamon threads running, and you must stop these as best you see fit depending on your program.
Calling System.exit() or setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); will force stop any other threads (and the whole program), meaning your code is less portable, and force-stopping threads is obviously dangerous (in a programming kind of way).
You can set a window listener to the frame so the program terminates after you close it.
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
}

Categories

Resources