I'd like to ask another question how to handle Windows' events in Java. To be specific, I'd like to know how to handle events such as mouse moved or mouse clicked in Windows XP and Vista. I want to wire my own custom behavior in my application to these events, even when my application is inactive or otherwise hidden.
All help is appreciated!
you can add e.g. a MouseListener to any JComponent by calling
addMouseListener()
There are different EventListeners which you can use instead of MouseListeners
KeyListener
WindowListener
ComponentListener
ContainerListener
FocusListener
...and many more
Check here for an detailed explanation
you can implement the MouseListener Interface completely or just use the convienience class MouseAdapter, which has method stubs, so you dont have to implement every single method.
check this sample:
public class MyFrame extends JFrame {
private MouseListener myMouseListener;
public MyFrame() {
this.setSize(300, 200);
this.setLocationRelativeTo(null);
// create the MouseListener...
myMouseListener = new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
System.out.println("clicked button " + e.getButton() + " on " + e.getX() + "x" + e.getY()); // this gets called when the mouse is clicked.
}
};
// register the MouseListener with this JFrame
this.addMouseListener(myMouseListener);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
MyFrame frame=new MyFrame();
frame.setVisible(true);
}
});
}
}
Related
I am following code I found on geeksforgeeks but the mouse listener isn't firing. I suspect that somehow the implementation of runnable is locking access to my board object, but I'm not sure. I'm in a similar boat to the OP of this post.
public class Game extends Canvas implements MouseListener {
JFrame jf = new JFrame();
Game() {
jf.getContentPane().add(this, BorderLayout.CENTER);
jf.setSize(new Dimension(500,500+30));
jf.setVisible(true);
jf.addMouseListener(this);
}
public void mouseClicked(MouseEvent e){
System.out.println("Hello World!");
}
public void mousePressed(MouseEvent e){}
public void mouseReleased(MouseEvent e){}
public void mouseEntered(MouseEvent e){}
public void mouseExited(MouseEvent e){}
public static void main(String[] args){
Game game = new Game();
}
}
I suspect but doubt that the mouse listener may not be functioning properly due to it being created in a non-static method, but I doubt that that is the problem. I've tried moving the declaration to the beginning of the constructor, but that didn't help.
The events will only register on the component which has focus. Which, in your program is your main panel, the Game class. So a quick fix would be just to change:
jf.addMouseListener(this);
to
addMouseListener(this);
But you should add the listener to any component you might want to get the events on, i.e. your main panel, the content pane, and jframe too.
The problem was with using Canvas instead of JPanel as the superclass. When I switched, the mouse listener started firing.
I created one JFrame with JDesktopPane, in which I am calling JInternalFrame. Now I want to close that internal frame by pressing escape key.
I tried 2-3 ways, but no output.
I did that by using code given below:
public static void closeWindow(JInternalFrame ji){
ActionListener close=New ActionListener(){
public void actionPerformed(ActionEvent e){
ji.dispose();
}
};
When I called above method from my intern frame class constructor by supplying its object , I was able to close it. But when there I write some other lines of code to the constructor. The above method call doesn't work. Please help me. I unable to find the problem in the code.
Also I tried to add KeyListener to internal frame, so I able to work with key strokes,but it also doesn't work.
Again I tried to setMnemonic to button as escape as below:
jButton1.setMnemonic(KeyEvent.VK_ESCAPE);
But also gives no output.
You need to implement the KeyListener interface, or add one that is Anonymous. In this example, I just implemented it.
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JFrame;
public class JInternalFrame extends JFrame implements KeyListener {
public JInternalFrame()
{
super();
// other stuff to add to frame
this.setSize(400, 400);
this.setVisible(true);
this.addKeyListener( this );
}
#Override
public void keyTyped(KeyEvent e) {
// Don't need to implement this
}
#Override
public void keyPressed(KeyEvent e) {
if( e.getKeyCode() == KeyEvent.VK_ESCAPE ) {
System.exit(0); //Change this to dispose or whatever you want to do with the frame
}
}
#Override
public void keyReleased(KeyEvent e) {
//Dont need to implement anything here
}
public static void main(String[] args)
{
JInternalFrame frame = new JInternalFrame();
}
}
Now if this is an internal jframe as mentioned, it is probably better to implement the keylistener in the JDesktopPane and call the dispose method on the JInternalFrame after pressing escape instead of implementing keylistener in this frame. It all depends on which GUI component has focus of input.
This issue is old now but I recently got stuck on a similar problem. Adding the key listener to the content pane of the internal frame instead of the internal frame itself did the job for me.
this.getContentPane().addKeyListener(this);
public class cPan extends JPanel implements ActionListener{
#Override
public void actionPerformed(ActionEvent arg0) {
}
}
I have the above code which catches actions from within my JPanel.
Im confused about how i would get an x,y cordinate from within my JPanel e.g. where i click
So if i click on 100,200 (x,y) i would like to be able to see this.
I've look the function givens from arg0 but cant find anything useful.
Where am i going wrong?
Use a MouseListener instead. This way, you'll get a MouseEvent, from which you can get the clicked point by calling MouseEvent#getPoint().
public class cPan extends JPanel implements MouseListener {
#Override
public void mouseClicked(MouseEvent e) {
Point p = e.getPoint();
// or
int x = e.getX();
int y = e.getY();
}
}
public class cPan extends JPanel implements ActionListener{
should be
public class cPan extends JPanel implements MouseListener{
more in Oracle turorial How to Write a Mouse Listener and with compare with wrong listener How to Write an Action Listener for MouseEvents
You need to add mouse listener:
JPanel panel = new JPanel ();
panel.setPreferredSize (new Dimension (640, 480));
panel.addMouseListener (new MouseAdapter() {
#Override
public void mouseClicked (MouseEvent e) {
JOptionPane.showMessageDialog(
e.getComponent (), "X: " + e.getX () + ", Y: " + e.getY ());
}
});
JFrame frame = new JFrame ("Click");
frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
frame.getContentPane ().setLayout (new BorderLayout ());
frame.getContentPane ().add (panel, BorderLayout.CENTER);
frame.pack ();
frame.setVisible (true);
ActionListener is used to notify you when, well, some kind of nondescript action has occurred.
There is no way to extract information about what caused the action (like mouse click or key action)
To get information about mouse events, you need to use a MouseListener attached to the component(s) you are interested in monitoring.
Check out How to use Mouse Listeners for more information
I got a problem with the KeyListener not responding(due to not gaining focus) when I switch between JPanels.
I have Google'd this and know that to fix this problem I need to use KeyBindings, but I don't like KeyBindings. So I was wondering, is there any other way?
Here is the init code of the JPanel that has an unresponsive KeyListener:
public void init()
{
setFocusable(true);
requestFocusInWindow();
requestFocus();
addMouseListener(new MouseInput());
addMouseMotionListener(new MouseInput());
addMouseWheelListener(new MouseInput());
addKeyListener(new KeyInput(p));
t = new Timer(10, this);
t.start();
}
Feel free to ask for more code samples if you need to!
The hacky solution is to call requestFocusInWindow() on the JPanel to make sure it has focus for KeyListener/KeyAdapter this should only be called after the Componnet has been added (though to be sure my component has focus I called it after the JFrame is refreshed via revalidate() and repaint()) for example:
public class MyUI {
//will switch to the gamepanel by removing all components from the frame and adding GamePanel
public void switchToGamePanel() {
frame.getContentPane().removeAll();
GamePanel gp = new GamePanel();//keylistener/keyadapter was added to Jpanel here
frame.add(gp);//add component. we could call requestFocusInWindow() after this but to be 98% sure it works lets call after refreshing JFrame
//refresh JFrame
frame.pack();
frame.revalidate();
frame.repaint();
gp.requestFocusInWindow();
}
}
class GamePanel extends JPanel {
public GamePanel() {
//initiate Jpanel and Keylistener/adapter
}
}
However you should use Swing KeyBindings (+1 to #Reimeus comment).
Have a read here to get familiar with them:
How to Use Key Bindings
Now that you have read that lets show another example to help clarify (though Oracle did a good job)
If we wanted to add a KeyBinding to a certain JComponent i.e JButton for Esc you would do:
void addKeyBinding(JComponent jc) {
jc.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0, false), "esc pressed");
jc.getActionMap().put("esc pressed", new AbstractAction() {
#Override
public void actionPerformed(ActionEvent ae) {
System.out.println("Esc pressed");
}
});
jc.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0, true), "esc released");
jc.getActionMap().put("esc released", new AbstractAction() {
#Override
public void actionPerformed(ActionEvent ae) {
System.out.println("Esc released");
}
});
}
the above method would be called like:
JButton b=..;//create an instance of component which is swing
addKeyBinding(b);//add keybinding to the component
Please note:
1) You would not need both KeyBindings, I just showed how to get different key state and act appropriately using Keybindings.
2) This method will add a Keybinding which will be activated as long as Esc is pressed and the component is in the window which has focus, you can change this by specifying another InputMap i.e:
jc.getInputMap(JComponent.WHEN_FOCUSED).put(..);//will only activated when component has focus
I have simple Swing GUI with main window JFrame and its main panel derive from JPanel. The panel has some buttons that can be clicked and generate events.
I want these events affect data stored in JFrame because it is my main application - it has some queues for thread, open streams and so on.
So how do I make my button in panel invoke callbacks in its parent frame? What is best practice of this for Java/Swing?
To invoke methods in the parent frame you need a reference to the parent frame. So your JPanel's constructor can be declared like this:
public MyPanel(MyFrame frame){
super();
this.frame = frame;
//the rest of your code
}
And in the JFrame you invoke this constructor like this:
panel = new MyPanel(this);//this refers to your JFrame
In the event handlers attached to your buttons you now have access to the frame and can invoke the various methods as needed.
button1.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
//do some stuff
frame.someMethod();//invoke method on frame
//do more stuff
}
});
Have a look on this tutorial for using SwingWorker.
Use addActionListener method on desired buttons specifying the class implementing ActionListener.
ActionListenerClass actionListenerObject = new actionListenerClass();
JButton b = new JButton("Button");
b.addActionListener(actionListenerObject);
public class ActionListenerClass implements ActionListener(){
//or better : actionListenerClass extends AbstractAction
public void actionPerformed(ActionEvent e) {
}
}
EDIT:
Yes, I know this. But the action
listener I want to be in parent JFrame
class - this is the problem
then extends JFrame class making the new derived class implementing the desired interface.
You can implement the ActionListener in your class that has the JFrame (or extends it):
class MyPanelClass {
public MyPanelClass(ActionListener al)
{
//...
JButton myButton = new JButton("Button");
myButton.addActionListener(al);
//...
}
}
class MainClass extends JFrame implements ActionListener {
public void someMethod() {
MyPanelClass mpc = new MyPanelClass(this);
}
#Override
public void ActionPerformed(ActionEvent ev) {
// your implementation
}
}