closing jframes current window and not the entire application - java

i need to close my applications current window without switching off the entire application my code is as follows to set a window visible but it closes all the windows whatever are currently open when i click on the right upper corner red cross button
private void lb_helpMouseClicked(java.awt.event.MouseEvent evt) {
new Reports().setVisible(true);
}
private void lb_certMouseClicked(java.awt.event.MouseEvent evt) {
new ChooseCert().setVisible(true);
}
private void lb_reportMouseClicked(java.awt.event.MouseEvent evt) {
new Reports().setVisible(true);
}

public void closeWindow() {
WindowEvent wev = new WindowEvent(this, WindowEvent.WINDOW_CLOSING);
Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(wev);
setVisible(false);
dispose();
}
public void closeApplication() {
System.exit(0);
}
After that just call the appropriate methods.

Related

Java: The escape key is always pressed after dispatchEvent() for WINDOW_CLOSING on a JFrame

I have a simple JFrame that asks a user for a confirmation to exit when they click X to close the window, this works fine. I also wanted the user to be presented with the same option if they also pressed the escape key (ESC), unfortunately it seems to be trapped in a state where the escape key seems to be constantly pressed when it is not. Where is the mistake and why?
public class Zz extends javax.swing.JFrame implements Events {
boolean exitAttempt = false;
java.awt.event.WindowEvent closeEvent;
//public Zz() {}
public static void main(java.lang.String[] args) {
Zz zz = new Zz();
zz.dostuff();
}
public void dostuff() {
setSize(800, 600);
setLocationRelativeTo(null);
setResizable(false);
setDefaultCloseOperation(javax.swing.JFrame.DO_NOTHING_ON_CLOSE);
addWindowListener(new java.awt.event.WindowAdapter() {
public void windowClosing(java.awt.event.WindowEvent we) {
exitAttempt = true;
}
});
closeEvent = new java.awt.event.WindowEvent(
this, java.awt.event.WindowEvent.WINDOW_CLOSING);
setVisible(true);
java.awt.Canvas canvas = new java.awt.Canvas();
canvas.setPreferredSize(new java.awt.Dimension(800, 600));
add(canvas);
Keys keys = new Keys();
addKeyListener(keys);
pack();
while (true) {
events(keys);
if (exitAttempt) {
if (javax.swing.JOptionPane.YES_OPTION ==
showConfirmDialog("Do you want to Exit ?",
"Confirmation:", javax.swing.JOptionPane.YES_NO_OPTION,
javax.swing.JOptionPane.QUESTION_MESSAGE, null)) {
exit();
break; //while loop
}
exitAttempt = false;
}
}
dispose();
}
public void triggerCloseEvent() {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
dispatchEvent(closeEvent);
}
});
}
public int showConfirmDialog(java.lang.Object message,
java.lang.String title, int optionType, int messageType,
javax.swing.Icon icon) {
return javax.swing.JOptionPane.showConfirmDialog(
this, message, title, optionType, messageType, icon);
}
public boolean exit() {
setDefaultCloseOperation(javax.swing.JFrame.EXIT_ON_CLOSE);
return true;
}
public void events(Keys keys) {
System.out.println((keys.getPressed())[java.awt.event.KeyEvent.VK_ESCAPE]);
if ((keys.getPressed())[java.awt.event.KeyEvent.VK_ESCAPE]) {
triggerCloseEvent();
}
}
}
interface Events {
public void events(Keys keys);
}
class Keys implements java.awt.event.KeyListener {
private final boolean[] pressed;
public Keys() {
pressed = new boolean[256];
}
public void keyTyped(java.awt.event.KeyEvent event) {}
public void keyPressed(java.awt.event.KeyEvent event) {
pressed[event.getKeyCode()] = true;
}
public void keyReleased(java.awt.event.KeyEvent event) {
pressed[event.getKeyCode()] = false;
}
public boolean[] getPressed() {
return pressed;
}
}
I have a simple JFrame that asks a user for a confirmation to exit when they click X to close the window, this works fine
Your design is incorrect.
You should NOT have a while (true) loop.
GUI's are event driven. You create the frame and make it visible. That is the end of the code in your main() method or constructor. The GUI will then sit there forever doing nothing.
However, eventually, the user will then generate events that the GUI responds to.
This means that the code to display the JOptionPane should be moved to the windowClosing() method of your WindowListener.
See: Closing an Application for some basics and helpful classes to use.
I also wanted the user to be presented with the same option if they also pressed the escape key
Don't use a KeyListener.
Swing was designed to be used with Key Bindings.
You can use the ExitAction contained in the Closing an Application link when creating your key bindings:
KeyStroke escapeKeyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0, false);
InputMap im = frame.getRootPane().getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
im.put(escapeKeyStroke, "escape");
frame.getRootPane().getActionMap().put("escape", new ExitAction());
Read the Swing tutorial. There are section on :
How to Uuse Key Bindings
How to Use Actions
to help explain how the above suggestions work.
The tutorial examples will also show you how to better structure your code and note that the never use a while (true) loop.

How to prevent that closing a JDialog closes the entire application

I have a main(screen) gui window and need to open a few "multi input" windows (jdialog or when not possible jframe), for example to add preferences (4 textfields with 2 filechoosers and 2 radiobuttons).
When pressing OK/Cancel in these JDialogs (or JFrames), my entire application closes.
I don't want that. How can I prevent that?
First try: I tried the intelliJ option "New -> Create Dialog class", which gives me a JDialog with OK/Cancel button. Pressing one of the buttons closes the JDialog and my entire application.
Second try: I wrote a class "by hand" which creates a JDialog (and also tried JFrame). Again: Pressing one of the buttons closes the JDialog and my entire application.
I removed "dispose()" and "setVisible(false)" options from theJDialog (JFrame), but still my entire application is closed.
main class method
public class mainScreen {
// Menu action listener (only relevant options)
class MenuActionListener implements ActionListener {
// menuListener
public void actionPerformed(ActionEvent ev) {
//myVariables myVars = new myVariables();
String[] dummy = null;
System.out.println("Selected: " + ev.getActionCommand());
switch(ev.getActionCommand()) {
case "Preferences":
showPreferencesDialog();
case "Exit":
System.exit(0);
break;
}
// method that opens the external class (see below in following code block)
private void showPreferencesDialog() {
prefJDialog myprefs = new prefJDialog(prefsPanel);
myprefs.showDialog();
boolean okPressed = myprefs.isOkPressed();
if (okPressed) {
JOptionPane.showMessageDialog(mainScreen.this.rootPanel,"OK pressed","About jExifToolGUI",JOptionPane.INFORMATION_MESSAGE);
} else {
JOptionPane.showMessageDialog(mainScreen.this.rootPanel,"Cancel pressed","About jExifToolGUI",JOptionPane.INFORMATION_MESSAGE);
}
}
// This is the class which is mention in the manifest
public mainScreen(JFrame frame) {
boolean preferences = false;
Preferences prefs = Preferences.userRoot();
createmyMenuBar(frame);
groupRadiobuttonsandListen();
fileNamesTableListener();
try {
myUtils.DisplayLogo(mainScreen.this.iconLabel);
} catch(IOException ex) {
System.out.println("Error reading Logo");
}
preferences = check_preferences();
if (!preferences) {
myUtils.checkExifTool(mainScreen.this.rootPanel);
}
programButtonListeners();
}
// main method in my main class for my project
public static void main(String[] args) {
JFrame frame = new JFrame("jExifToolGUI");
frame.setContentPane(new mainScreen(frame).rootPanel);
//frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
The JDialog class/method that is called from the main class
package org.hvdw.jexiftoolgui;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class prefJDialog extends JDialog {
private JButton okButton;
private JButton cancelButton;
private JPanel prefsPanel;
private boolean okPressed;
public prefJDialog(JPanel prefsPanel) {
super(JOptionPane.getFrameForComponent(prefsPanel), true);
this.prefsPanel = prefsPanel;
setTitle("Preferences");
initDialog();
}
public void showDialog() {
setSize(800, 768);
double x = getParent().getBounds().getCenterX();
double y = getParent().getBounds().getCenterY();
setLocation((int) x - getWidth() / 2, (int) y - getHeight() / 2);
setVisible(true);
}
private void initDialog() {
JPanel pane = new JPanel();
pane.setLayout(new BoxLayout(pane, BoxLayout.Y_AXIS));
pane.setBorder(BorderFactory.createEmptyBorder(10, 10, 5, 10));
add(pane);
pane.add(Box.createVerticalGlue());
FlowLayout l = new FlowLayout(FlowLayout.RIGHT);
JPanel buttonsPane = new JPanel(l);
okButton = new JButton("Save"); //$NON-NLS-1$
buttonsPane.add(okButton);
pane.getRootPane().setDefaultButton(okButton);
cancelButton = new JButton("CANCEL"); //$NON-NLS-1$
buttonsPane.add(cancelButton);
buttonsPane.setMaximumSize(new Dimension(Short.MAX_VALUE, (int) l.preferredLayoutSize(buttonsPane).getHeight()));
pane.add(buttonsPane);
addListeners();
}
private void addListeners() {
okButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
//saveProperties();
setVisible(false);
okPressed = true;
//close();
// dispose();
}
});
cancelButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
setVisible(false);
//dispose();
//close();
okPressed = false;
}
});
}
public boolean isOkPressed() {
return okPressed;
}
/*public void close() {
WindowEvent winClosingEvent = new WindowEvent(this, WindowEvent.WINDOW_CLOSING);
Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(winClosingEvent);
}*/
}
So how do I prevent that upon clicking OK or Cancel in the JDialog, the entire application closes. That needs to stay open until the user clicks the "window close" X in the top-right, or from the menu "File -> Exit"
I have searched Google for several days, but can't find a solution (and one same question without answer).
Edit:
After Patrick's answer I changed the close method to
public void close() {
this.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
}
And removed the /* and */.
I also activated the close(); in the listeners again, but it doesn't make a difference. My main app is still closed.
switch(ev.getActionCommand()) {
case "Preferences":
showPreferencesDialog();
case "Exit":
System.exit(0);
break;
And the problem is that you don't have a break statement in your switch case so the code falls through to the "Exit" logic and does a System.exit(0)
This is why we need a proper "MCVE" with every question. When you post random pieces of code we can't see the entire logic flow.

Dispose frame after start frame Java Swing

I'm new to Stackoverflow. I have a problem in java/swing with project to school.
The project is a testing service. I want to run an additional window before running the main program that checks the connection to the server. After checking the connection it should start the main window of the program and disappear. If I manually click startProgramButton it's all right. However, if the program is connected to the server at startup, the main window of the program is started, but this window does not disappear.
public class PreForm extends javax.swing.JFrame {
/**
* Creates new form PreForm
*/
MainForm form1;
Settings form2;
public PreForm() {
initComponents();
checkConnection();
}
private void settingsButtonActionPerformed(java.awt.event.ActionEvent evt) {
errorLabel.setText("");
form2 = new Settings();
form2.setVisible(true);
}
private void runProgramButtonActionPerformed(java.awt.event.ActionEvent evt) {
checkConnection();
}
private void checkConnection() {
if (hostAvailabilityCheck()) {
runMainProgram();
} else
errorLabel.setText("<html>Error connect to server!<br>"
+ "Check connect settings and try again!</html>");
}
private boolean hostAvailabilityCheck() {
try (Socket s = new Socket(SettingsFile.getAddress(), Integer.parseInt(SettingsFile.getPort()))) {
return true;
} catch (IOException ex) {
/* ignore */
}
return false;
}
private void runMainProgram() {
this.setVisible(false);
form1 = new MainForm();
form1.setVisible(true);
}
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new PreForm().setVisible(true);
}
});
}
So, after running the program, the checkConnection method is executed. Then the runMainProgram method is executed. And that's where this.setVisible (false) code comes in, which should hide the window, but it stays. But only if the checkConnection method is started in the constructor. If you run it manually through the startProgramButton, this window is hidden.

Java Swing, restore from system tray not working in Linux

I am creating an application in Java and I would like that when you minimize to an icon, the application will have to "hide" in the system tray.
The code I use is this: (the significant part of the code)
myFrame = new JFrame();
myFrame.addWindowListener(new WindowAdapter() {
#Override
public void windowIconified(WindowEvent e) {
PutTray();
}
#Override
public void windowDeiconified(WindowEvent e) {
System.out.println("Deiconified");
}
});
This is a "PutTray" function:
private void PutTray()
{
try
{
tray.add(trayIcon); // Initialized elsewhere
myFrame.setVisible(false);
} catch (AWTException e) {
System.err.println(e);
}
}
To restore (via option in the pop-up menu when you press the icon minimized):
MenuItem show = new MenuItem("Show");
show.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
myFrame.setVisible(true);
myFrame.setState(JFrame.NORMAL);
tray.remove(trayIcon);
}
});
The code works perfectly on Windows 8, but it does not work on Linux (Kali Linux and even Ubuntu).
Why Windows yes and Linux no?
EDIT:
On Linux, after you press the command to show the application, it appears for a very small moment, and then minimizes again. Basically is triggered the event "windowDeiconified" and immediately after the event "windowIconified" without taking the time to do something else and then the application is shown in the system tray.
As Dan Getz suggests, I also thought the order of setVisible and setState should be inverted since the javadoc for setState says:
If the frame is not visible on the
* screen, the events may or may not be
* generated.
but this didn't help.
The one thing that did help though was replacing setVisible(false) with dispose(). They are similar in that you can use setVisible(true) to reopen a disposed window. You can read more about it here: JDialog setVisible(false) vs dispose()
I'll try to find an explanation and come back with it :)
SSCCE to simulate OP problem:
public class Test {
private JFrame myFrame;
public Test() {
myFrame = new JFrame();
myFrame.setVisible(true);
myFrame.setSize(300, 300);
myFrame.addWindowListener(new WindowAdapter() {
#Override
public void windowIconified(WindowEvent e) {
PutTray();
}
});
}
private void PutTray() {
myFrame.setVisible(false); //replace with dispose(); and it's ok
Timer t = new Timer(1000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent actionEvent) {
myFrame.setVisible(true);
}
});
t.setRepeats(false);
t.start();
}
public static void main(String[] args) {
new Test();
}
}
I think you are getting it wrong!
Maybe you are confused about deiconified and visibility
windowIconified()
will be called when we click minimize button
and
windowDeiconified()
is called when we restore it from taskbar and not system tray!
In order to restore from system tray you need to use this
trayIcon.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
window.setVisible(true);
}
});
Basically i don't think the difference between dispose() & setVisible() will bother you in this specific problem
Still, my recommendation is to use setVisible() here

Why wont my JFrame hide?

I'm in the process of creating a GUI in Netbeans 6.1 for my senior design project but i've run into an annoying snag. Temporary Windows like my login PopUp and others wont disappear when i tell it. I've been researching how to solve this for about 2 months on an off. I've even mad a separate thread for my Pop Up but it still wont work....the only way it will disappear if i literally dont mess with any of the other GUI components....my sample code should help describe my anger...dont mind the shadow code, it was for testing purposes, which obviously didnt help.
//This method is called once a user presses the "first" login button on the main GUI
public synchronized void loginPopUpThread() {
doHelloWorld = new Thread(){
#Override
public synchronized void run()
{
try
{
loginPopUpFrame.pack();
loginPopUpFrame.setVisible(true);
System.out.println("waitin");
doHelloWorld.wait();
System.out.println("Not Sleepin..");
loginPopUpFrame.pack();
loginPopUpFrame.setVisible(false);
}
catch (InterruptedException e)
{
}
}
};
doHelloWorld.start();
//This is called when the "second" loginB is pressed and the password is correct...
public synchronized void notifyPopUp() {
synchronized(doHelloWorld) {
doHelloWorld.notifyAll();
System.out.println("Notified");
}
}
I've also tried Swing Utilities but maybe i implemented it wrong as it's my first time using them. It essentially does the same thing as the code above except the window freezes when it gets to wait, which the above code doesnt do:
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public synchronized void run() {
try
{
loginPopUpFrame.pack();
loginPopUpFrame.setVisible(true);
System.out.println("waitin");
wait();
System.out.println("Not Sleepin.");
loginPopUpFrame.pack();
loginPopUpFrame.setVisible(false);
}
catch (InterruptedException e)
{
}
}
});
PLEASE HELP ME!!!
Rules of thumb:
Don't manipulate GUI components in arbitrary threads; always arrange to manipulate them in the event thread
Never wait or sleep inside the event thread (so, never inside code sent to invokeLater())
So the answer to how you solve this problem is "some other way"...
Standing back from the problem a bit, what is it you're actually trying to do? If you just want a login dialog to wait for the user to enter user name and password, is there a reason not to just use a modal JDialog (after all, that's what it's there for...).
If you really do want some arbitrary thread to wait for a signal to close the window/manipulate the GUI, then you need to do the waiting in the other thread, and then make that thread call SwingUtilities.invokeLater() with the actual GUI manipulation code.
P.S. There are actually some GUI manipulation methods that it is safe to call from other threads, e.g. calls that are "just setting a label" are often safe. But which calls are safe isn't terribly well-defined, so it's best just to avoid the issue in practice.
The Swing components should only be manipulated by the swing event dispatch thread.
class SwingUtilites has methods to submit tasks to the dispatch thread.
It is difficult to diagnose your problem. I'm not sure what you're trying to do with the wait methods, but I recommend leaving wait/notify alone.
This code has two frames - when you create a second frame, the first is hidden until you close it.
public class SwapFrames {
private JFrame frame;
private JFrame createMainFrame() {
JButton openOtherFrameButton = new JButton(
"Show other frame");
frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container contentPane = frame.getContentPane();
contentPane.setLayout(new FlowLayout());
contentPane.add(openOtherFrameButton);
frame.pack();
openOtherFrameButton
.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
onClickOpenOtherFrame();
}
});
return frame;
}
private void onClickOpenOtherFrame() {
frame.setVisible(false);
JFrame otherFrame = new JFrame();
otherFrame
.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
otherFrame.setContentPane(new JLabel(
"Close this to make other frame reappear."));
otherFrame.pack();
otherFrame.setVisible(true);
otherFrame.addWindowListener(new WindowAdapter() {
#Override
public void windowClosed(WindowEvent e) {
frame.setVisible(true);
}
});
}
public static void main(String[] args) {
JFrame frame = new SwapFrames().createMainFrame();
frame.setVisible(true);
}
}
Because I don't see any evidence of them in your code, I'm going to suggest you read up on using event listeners rather than trying to "wait" for code to finish.
It isn't entirely clear what you're trying to achieve, but you might be better off with a modal dialog:
public class DialogDemo {
public JFrame createApplicationFrame() {
JButton openDialogButton = new JButton("Open Dialog");
final JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container container = frame.getContentPane();
container.setLayout(new FlowLayout());
container.add(openDialogButton);
frame.pack();
openDialogButton
.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
onOpenDialog(frame);
}
});
return frame;
}
private void onOpenDialog(JFrame frame) {
JDialog dialog = createDialog(frame);
dialog.setVisible(true);
}
private JDialog createDialog(JFrame parent) {
JButton closeDialogButton = new JButton("Close");
boolean modal = true;
final JDialog dialog = new JDialog(parent, modal);
dialog
.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
Container container = dialog.getContentPane();
container.add(closeDialogButton);
dialog.pack();
dialog.setLocationRelativeTo(parent);
closeDialogButton
.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
dialog.setVisible(false);
}
});
return dialog;
}
public static void main(String[] args) {
new DialogDemo().createApplicationFrame().setVisible(
true);
}
}
How about doing simply:
//This method is called once a user presses the "first" login button on the main GUI
public void loginPopUpThread() {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
loginPopUpFrame.pack();
loginPopUpFrame.setVisible(true);
}
};
}
//This is called when the "second" loginB is pressed and the password is correct...
public void notifyPopUp() {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
loginPopUpFrame.setVisible(false);
}
};
}
What you really want to be using is a modal JDialog.
Note, bits of this are left out. It's your homework/project.
public void actionPerformed(ActionEvent e)
{
// User clicked the login button
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
LoginDialog ld = new LoginDialog();
// Will block
ld.setVisible(true);
}
});
}
public class LoginDialog extends JDialog
{
public LoginDialog()
{
super((Frame)null, "Login Dialog", true);
// create buttons/labels/components, add listeners, etc
}
public void actionPerformed(ActionEvent e)
{
// user probably clicked login
// valid their info
if(validUser)
{
// This will release the modality of the JDialog and free up the rest of the app
setVisible(false);
dispose();
}
else
{
// bad user ! scold them angrily, a frowny face will do
}
}
}

Categories

Resources