Java - how do I check whether a JFrame is closed - java

When a user clicks the red 'X' button of a JFrame, how do I detect whether the JFrame is open or closed? I have a swing timer where the JFrame keeps updating it's label until the user closes down the JFrame.
int delay = 1000; //milliseconds
final Timer timer = new Timer(delay, null);
timer.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
tempLabel.setVisible(true);
String tmp = "test";
tempLabel.setText("Temperature : " + tmp);
// timer.stop();
}
});
timer.start();

You have to implement either the WindowStateListener or the WindowListener. If you use the WindowListener it could look like this:
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import javax.swing.Timer;
public class Foo implements WindowListener {
private Timer timer;
public static void main(String args[]){
initTimerComponent();
}
private void initTimerComponent() {
int delay = 1000; //milliseconds
timer = new Timer(delay, null);
timer.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
tempLabel.setVisible(true);
String tmp = "test";
tempLabel.setText("Temperature : " + tmp);
}
});
timer.start();
}
#Override
public void windowOpened(WindowEvent e) { }
#Override
public void windowClosing(WindowEvent e) {
timer.stop();
}
#Override
public void windowClosed(WindowEvent e) { }
#Override
public void windowIconified(WindowEvent e) { }
#Override
public void windowDeiconified(WindowEvent e) { }
#Override
public void windowActivated(WindowEvent e) { }
#Override
public void windowDeactivated(WindowEvent e) { }
}
You have to implement them all as WindowListener is an interface and the first concrete class implementing an interface is forced to implement all its abstract methods. But you actually need just one method.
Use this method
public void windowClosing(WindowEvent e) {
timer.stop();
}
to stop your timer as soon as the window is closing after the user clicked the red X.

Answer
addWindowListener(new WindowAdapter() {
//for closing
#Override
public void windowClosing(WindowEvent e) {
JOptionPane.showMessageDialog(null, "Closing");
}
//for closed
#Override
public void windowClosed(WindowEvent e) {
}
});

Related

Delaying jtextfield document listener for validation

I'm trying to check a JFormattedTextField after a value has been entered to make sure it does not match any other values entered in the other similar fields. It becomes a real pain if this check happens repeatedly while the user is typing because I want to provide an error message and I need to implement a number of changes if the value changes. But inputs like 123 will match 12 before the 3 is typed even though no error has really been made yet. Thus the need for a delay. So I'm trying to use a document listener but delay it until the user has validated (as accepted by the text field, by action or shifting focus) the entry.
I thought I had a good method, and it nearly works. My plan was to use a document listener to set up focus and action listeners. Unfortunately, I seem to end up with tons of focus and action listeners since the document listener keeps adding them. That means the error message and subsequent processing happen a ridiculous number of times instead of once. I've tried two work-arounds: 1) remove focus and action listeners before adding new ones, and 2) use a boolean to mark the existence of the focus and action listeners to avoid creating them again.
sscce (I'm new here, should I leave out all the includes?):
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
public class Tester {
private JFrame frame;
private JTextField textField;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Tester window = new Tester();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public Tester() {
initialize();
}
private void initialize() {
frame = new JFrame();
frame.setBounds(50, 50, 200, 50);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
textField = new JTextField("Change this.");
textField.getDocument().addDocumentListener(new DocumentListener() {
public void insertUpdate(DocumentEvent e) {
trigger();
}
public void removeUpdate(DocumentEvent e) {
trigger();
}
public void changedUpdate(DocumentEvent e) {
trigger();
}
public void trigger() {
textField.addFocusListener(new FocusListener() {
public void focusGained(FocusEvent e) {
}
public void focusLost(FocusEvent e) {
System.out.println("You changed the text to: " + textField.getText());
}
});
textField.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("You changed the text to: " + textField.getText());
}
});
}
});
frame.add(textField);
}
}
So attempted fix 1 was to place textField.removeFocusListener(null) and textField.removeActionListener(null) just before the two textField.add... lines. Nothing changed from attempted fix 1. Attempted fix 2 was to create a boolean triggeringEvent outside of trigger() and then start trigger() with if(triggeringEvent == false) { triggeringEvent = true; ... all the focus and action listener lines. Attempted fix 2 just left me with nothing triggering at all.
Thank you for any insight anyone can provide!!!
Edit: I had tried Boann's addChangeListener, but that triggers incessantly, too, and it even triggers when the value hasn't been changed.
Edit: I thought I found a solution by adjusting attempted fix 2, but it fails with more than one JTextField:
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
public class Tester {
private JFrame frame;
private JTextField textField;
private boolean eventTrigger = false;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Tester window = new Tester();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public Tester() {
initialize();
}
private void initialize() {
frame = new JFrame();
frame.setBounds(50, 50, 200, 50);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
textField = new JTextField("Change this.");
textField.getDocument().addDocumentListener(new DocumentListener() {
public void insertUpdate(DocumentEvent e) {
if(eventTrigger == false) {
trigger();
}
}
public void removeUpdate(DocumentEvent e) {
if(eventTrigger == false) {
trigger();
}
}
public void changedUpdate(DocumentEvent e) {
}
public void trigger() {
eventTrigger = true;
textField.addFocusListener(new FocusListener() {
public void focusGained(FocusEvent e) {
}
public void focusLost(FocusEvent e) {
System.out.println("You changed the text to: " + textField.getText());
eventTrigger = false;
}
});
textField.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("You changed the text to: " + textField.getText());
eventTrigger = false;
}
});
}
});
frame.add(textField);
}
}
You can see in this. If you start hopping between fields there are a whole bunch of extra times it triggers. It works fine for the first one you try adjusting, but then it fails.
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
public class Tester {
private JFrame frame;
private JPanel panel;
private JTextField textField1;
private JTextField textField2;
private boolean eventTrigger = false;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Tester window = new Tester();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public Tester() {
initialize();
}
private void initialize() {
frame = new JFrame();
frame.setBounds(50, 50, 200, 100);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
panel = new JPanel();
panel.setLayout(new GridLayout(0,1,0,0));
textField1 = new JTextField("Change the first.");
textField2 = new JTextField("Change the second.");
textField1.getDocument().addDocumentListener(new DocumentListener() {
public void insertUpdate(DocumentEvent e) {
if(eventTrigger == false) {
trigger();
}
}
public void removeUpdate(DocumentEvent e) {
if(eventTrigger == false) {
trigger();
}
}
public void changedUpdate(DocumentEvent e) {
}
public void trigger() {
eventTrigger = true;
textField1.addFocusListener(new FocusListener() {
public void focusGained(FocusEvent e) {
}
public void focusLost(FocusEvent e) {
System.out.println("You changed the text to: " + textField1.getText());
eventTrigger = false;
}
});
textField1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("You changed the text to: " + textField1.getText());
eventTrigger = false;
}
});
}
});
textField2.getDocument().addDocumentListener(new DocumentListener() {
public void insertUpdate(DocumentEvent e) {
if(eventTrigger == false) {
trigger();
}
}
public void removeUpdate(DocumentEvent e) {
if(eventTrigger == false) {
trigger();
}
}
public void changedUpdate(DocumentEvent e) {
}
public void trigger() {
eventTrigger = true;
textField2.addFocusListener(new FocusListener() {
public void focusGained(FocusEvent e) {
}
public void focusLost(FocusEvent e) {
System.out.println("You changed the text to: " + textField2.getText());
eventTrigger = false;
}
});
textField2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("You changed the text to: " + textField2.getText());
eventTrigger = false;
}
});
}
});
panel.add(textField1);
panel.add(textField2);
frame.add(panel);
}
}

KeyListener won't listen on JPanel

It's a very simple program, but for some reason when I debug it and set breakpoints at the keyPressed, keyReleased and keyTyped method, the program never stops there.
mainKeyListener = new KeyListener() {
public void keyPressed(KeyEvent e) {
System.out.println("KEY PRESSED");
repaint();
}
}
#Override
public void keyReleased(KeyEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void keyTyped(KeyEvent arg0) {
// TODO Auto-generated method stub
}
};
Here I add it to a JPanel, which is the exact size of the frame and the only object on it:
JPanel backgroundPanel = new JPanel();
backgroundPanel.setBounds(0,0, 400, 500);
backgroundPanel.addKeyListener(mainKeyListener);
backgroundPanel.setFocusable(true);
getContentPane().add(backgroundPanel);
Your problem is laying in focused element. I think that your panel lost the focus.
Note:
To fire keyboard events, a component must have the keyboard focus. It can be solved in many ways for your example you can use KeyboardFocusManager for example like this:
KeyboardFocusManager focusManager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
focusManager.addKeyEventDispatcher(new KeyEventDispatcher() {
public boolean dispatchKeyEvent(KeyEvent e) {
if(focusManager.getFocusOwner()!=backgroundPanel){
focusManager.redispatchEvent(backgroundPanel,e);
return true;}
else return false;
}
});
Also try to use Key Bindings http://docs.oracle.com/javase/tutorial/uiswing/misc/keybinding.html
Hi this should work for you.
public class Gui extends JFrame
{
private JPanel backgroundPanel = new JPanel();
public Gui() throws HeadlessException
{
this.setLayout(new GridLayout(1,1));
setPanelProps();
backgroundPanel.addKeyListener(createListener());
this.add(backgroundPanel);
this.setVisible(true);
this.setSize(new Dimension(400,500));
}
public void setPanelProps(){
backgroundPanel.setBounds(0, 0, 400, 500);
backgroundPanel.setSize(new Dimension(400,500));
backgroundPanel.setFocusable(true);
backgroundPanel.setBackground(new Color(50,60,70));
}
public KeyListener createListener(){
return new KeyListener() {
#Override
public void keyTyped(KeyEvent e)
{
System.out.println("KEY TYPED");
}
public void keyPressed(KeyEvent e) {
System.out.println("KEY PRESSED");
repaint();
}
#Override
public void keyReleased(KeyEvent e)
{
System.out.println("KEY RELEASED");
}
};
}
}
public class GuiRun
{
public static void main(String[] args)
{
Gui gui = new Gui();
}
}

Cannot make a keylistener work

I have public class MainFrame extends JFrame implements ActionListener {
and then later on:
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == e.VK_LEFT) {
int x = ball.getX() + 1;
ball.setX(x);
}
}
however it does not seem to respond when I believe it should.
If I add keylistener instead of actionlister I cannot compile which I can't understand. I'm new to java however i'm used to C#
You need to implement java.awt.event.KeyListener not a ActionListener to listen for key events.
You need to register your listener on the element (frame) you want to listen on by invoking addKeyListener(...).
Example:
public class TestFrame extends JFrame implements KeyListener {
public static void main(String[] args) throws FileNotFoundException {
TestFrame testFrame = new TestFrame();
testFrame.setSize(100, 100);
testFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
testFrame.addKeyListener(testFrame);
testFrame.setVisible(true);
}
#Override
public void keyTyped(KeyEvent e) { }
#Override
public void keyPressed(KeyEvent e) {
System.out.println(e);
}
#Override
public void keyReleased(KeyEvent e) { }
}

Java: Cancel Button does not close the window for JFrame

I want the window to close when I press on Cancel button, but it's not working.
Code:
public class FirstClass{
private JFrame frame;
private JButton btnCancel;
public FirstClass() {
frame = new JFrame("GRIIS Data Transfer [Mobile to PC]");
frame.setBounds(200,200,900,450);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(null);
btnCancel = new JButton("Cancel");
btnCancel.setBounds(800, 5, 85, 25);
frame.add(btnCancel);
btnCancel.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
frame.addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(WindowEvent e) {
super.windowClosing(e);
System.exit(0);
}
});
}
});
}//end of constructor
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
FirstClass window = new FirstClass();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
}
Please let me know in case of changes needed in the code.
btnCancel.addActionListener()
so my code will work and close the application when I press on Cancel button.
Dont use window listner it gives event at time of closing, try
btnCancel.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.exit(0);
}});
No need to override WindowListener method,
public void actionPerformed(ActionEvent e) {
System.exit(0);
}

Java MouseEvent, check if pressed down

I have a class that implements MouseListener (JPanel). When I click on the panel something happens. What I want is some kind of while-loop that loops as long as left mousebutton is pressed down.
#Override
public void mousePressed(MouseEvent e) {
while(e.isPressedDownD) { // <--
//DO SOMETHING
}
}
This obviously doesn't work, but I hope you understand what I'm trying to achieve.
The whole class for those that are interested:
package control;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import model.GridModel;
import view.GUIView;
public class MapListener implements MouseListener{
private GridModel model;
private GUIView view;
private int posX;
private int posY;
public MapListener(GridModel model, GUIView view) {
this.model = model;
this.view = view;
}
#Override
public void mouseClicked(MouseEvent e) {
posX = e.getX();
posY = e.getY();
model.setMouseAtX(posX);
model.setMouseAtY(posY);
view.paintTile();
System.out.println("X: " + posX + " Y: " + posY);
}
#Override
public void mouseEntered(MouseEvent e) {
}
#Override
public void mouseExited(MouseEvent arg0) {
}
#Override
public void mousePressed(MouseEvent e) {
while(e.getModifiers() == MouseEvent.MOUSE_PRESSED) { //Obviously doesn't work
//DO SOMETHING
}
}
#Override
public void mouseReleased(MouseEvent arg0) {
}
}
As pointed out by other answers, the place to do your work is not in the mouse event listener methods.
Also there is no explicit "mouse pressed" notion in MouseEvent, so you must track that yourself. I have provided an example of how to do this. Also note the MouseEvent.BUTTON1 references, as this is just to track the state of the left mouse button.
This is where you must start to learn about concurrency. For that reason, I've added in a synchronized method as you need to be aware that funny things happen when multiple threads access properties at the same time, and synchronized is a mechanism for keeping this sane. Consider it further reading beyond the scope of this example.
Untested, but this should work:
volatile private boolean mouseDown = false;
public void mousePressed(MouseEvent e) {
if (e.getButton() == MouseEvent.BUTTON1) {
mouseDown = true;
initThread();
}
}
public void mouseReleased(MouseEvent e) {
if (e.getButton() == MouseEvent.BUTTON1) {
mouseDown = false;
}
}
volatile private boolean isRunning = false;
private synchronized boolean checkAndMark() {
if (isRunning) return false;
isRunning = true;
return true;
}
private void initThread() {
if (checkAndMark()) {
new Thread() {
public void run() {
do {
//do something
} while (mouseDown);
isRunning = false;
}
}.start();
}
}
Why do so many of these answers wrongly assert that there is no explicit "mouse pressed" notion in MouseEvent?
Although the other commenters are correct that the OP should not be doing all that stuff in an event handler, there are other situations in which querying the button state in a mouse listener is useful. In those cases, you actually CAN determine the button down state. For example:
#Override
public void mouseExited(MouseEvent event) // Or any other mouse event handler...
{
int buttonsDownMask = MouseEvent.BUTTON1_DOWN_MASK
| MouseEvent.BUTTON2_DOWN_MASK
| MouseEvent.BUTTON3_DOWN_MASK; // Or whichever buttons you care about...
if ( (event.getModifiersEx() & buttonsDownMask) != 0 )
System.out.println("Hey! Some button is pressed!");
}
Notice in particular the use of the MouseEvent.getModifiersEx() method, along with MouseEvent.BUTTON1_DOWN_MASK and friends.
You could create a new Thread containing your while loop.
You start that Thread when the mouse button is pressed. You stop it when the mouse button is released.
You shouldn't be doing that in an event handler as no more events will be processed until the event handler exits.
What you want to achieve can be done with a separate worker thread. Create the thread from the mousePressed listener, do whatever you want to do in the thread (this should contain the while loop) and make the thread exit when the mouse is released (your mouseReleased listener should notify the thread).
for example
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class ClickListener extends MouseAdapter implements ActionListener {
private final static int clickInterval = (Integer) Toolkit.getDefaultToolkit().getDesktopProperty("awt.multiClickInterval");
private MouseEvent lastEvent;
private Timer timer;
public ClickListener() {
this(clickInterval);
}
public ClickListener(int delay) {
timer = new Timer(delay, this);
}
#Override
public void mouseClicked(MouseEvent e) {
/*if (e.getClickCount() > 2) {
return;
}
lastEvent = e;
if (timer.isRunning()) {
timer.stop();
doubleClick(lastEvent);
} else {
timer.restart();
}*/
if (timer.isRunning() && !e.isConsumed() && e.getClickCount() > 1) {
System.out.println("double");
timer.stop();
} else {
timer.restart();
}
}
#Override
public void actionPerformed(ActionEvent e) {
timer.stop();
singleClick(lastEvent);
}
public void singleClick(MouseEvent e) {
}
public void doubleClick(MouseEvent e) {
}
public static void main(String[] args) {
JFrame frame = new JFrame("Double Click Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.addMouseListener(new ClickListener() {
#Override
public void singleClick(MouseEvent e) {
System.out.println("single");
}
#Override
public void doubleClick(MouseEvent e) {
System.out.println("double");
}
});
frame.setPreferredSize(new Dimension(200, 200));
frame.pack();
frame.setVisible(true);
}
}

Categories