KeyListener won't listen on JPanel - java

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();
}
}

Related

KeyListener on function keys

I want to listen on F3 key pressed inside my JFrame.
How is this possible?
Something like this:
this.addKeyListener(new KeyAdapter() {
#Override
public void keyTyped(KeyEvent e) {
if (e.getKeyCode() == F3)
MyFrame.this.dispose();
}
});
Using solution from Benson99 as a springboard, I think the following should work.
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JFrame;
public class KeyListenFrame extends JFrame {
public KeyListenFrame() {
JFrame frame = new JFrame();
frame.setTitle("Key Listener Frame - Press F3 to close frame");
frame.setSize(600, 300);
frame.addKeyListener(new KeyListener() {
#Override
public void keyTyped(KeyEvent e) {
}
#Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_F3) {
System.out.println("Pressed " + e.getKeyCode());
System.out.println("Closing frame");
frame.dispose();
} else {
System.out.println("Pressed " + e.getKeyCode());
}
}
#Override
public void keyReleased(KeyEvent e) {
}
});
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
public static void main(String[] args) {
KeyListenFrame keyListenFrame = new KeyListenFrame();
}
}
You have to use keyPressed for the function keys. Try this code and press keys. Function keys won't fire a key typed event.
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setSize(200,200);
frame.addKeyListener(new KeyListener() {
#Override
public void keyTyped(KeyEvent e) {
System.out.println("from keyTyped: " + e.getKeyCode());
}
#Override
public void keyPressed(KeyEvent e) {
System.out.println("from keyPressed: " + e.getKeyCode());
}
#Override
public void keyReleased(KeyEvent e) {
}
});
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
If I want to do this.getInputMap() in my JFrame, this is impossible
Because a JFrame is NOT a JComponent.
You add Key Bindings to a JComponent. In this case you would add the Key Bindings to the "root pane" of the JFrame.
Read the section from the Swing tutorial on How to Use Root Panes for basic information.
I also showed you how to access the root pane in the link I provide above on Key Bindings.

How to Change Default Inputs for JComboBox and JButton

How do I make the Enter key trigger a JComboBox or JButton in a GUI rather than having to hit the Space key? I have an assortment of text fields and check boxes with buttons and combo boxes in between. I'd like to avoid having to switch between hitting space and enter and rather only have to hit enter for all components.
package koning.personal.dungeonsanddragons;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class test {
JFrame window = new JFrame("testGUI");
JPanel windowPanel = new JPanel();
public static JLabel labelSize;
public static JComboBox<String> comboSize;
public static JLabel labelButton;
public static JButton buttonButton;
public test () {
super();
labelSize = new JLabel("Monster Size:");
String[] sizeChoices = { "None", "Tiny", "Small", "Medium", "Large", "Huge", "Colossal"};
comboSize = new JComboBox<String>(sizeChoices);
comboSize.setToolTipText("The creature's size.");
labelButton = new JLabel("Button:");
buttonButton = new JButton();
windowPanel.setLayout(new FlowLayout());
windowPanel.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
windowPanel.add(labelSize);
windowPanel.add(comboSize);
windowPanel.add(labelButton);
windowPanel.add(buttonButton);
windowPanel.setVisible(true);
window.setSize(500, 500);
window.setLayout(new FlowLayout());
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setVisible(true);
window.add(windowPanel);
comboSize.addActionListener(handler);
buttonButton.addActionListener(handler);
}
ActionHandler handler = new ActionHandler();
public class ActionHandler implements ActionListener {
public void actionPerformed(ActionEvent eventFocus){
if (eventFocus.getSource() == comboSize){
buttonButton.requestFocusInWindow();
}
if (eventFocus.getSource() == buttonButton){
comboSize.requestFocusInWindow();
}
}
}
#SuppressWarnings("unused")
public static void main(String[] args) {
test GUITest = new test();
}
}
You can add a KeyListener and execute doClick
JButton btn = new JButton();
btn.addKeyListener(new KeyListener() {
#Override
public void keyTyped(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_ENTER)
btn.doClick();
}
#Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
}
#Override
public void keyPressed(KeyEvent e) {
// TODO Auto-generated method stub
}
});
If the goal is to have something happen when the enter button is pressed (pressed once and something happens with all the components) then you can add a KeyListener to the JFrame:
JFrame frame = new JFrame("Examplpe");
//here you create and add the components to the frame
and then you can add a KeyListener:
frame.addKeyListener(new KeyListener(
#Override
public void keyTyped(KeyEvent e) {
if(e.getKeyCode == KeyEvent.VK_ENTER){//this is the if block I'm refering to in the following explanation
//do something with all the components
}
}
#Override
public void keyReleased(KeyEvent e) {}
#Override
public void keyPressed(KeyEvent e) {}
}
and then when you press Enter, the code inside the if block will be executed.
Hope this helps :)

Java Swing GUI. Activating/Firing more buttons while keeping the mousebutton pressed

If I want to do an action, if a button is pressed I can use a ActionListener. But now if I want to activate more buttons by keeping the mousebutton pressed.
How can I implement this?
Thanks
Add a ChangeListener to the buttons ButtonModel, monitor for a change to the isPressed state.
The trick then is setting up some process which can then add the other components, in this simple example, I've used a Swing Timer, which will add roughly 40 new components a second while the button is pressed
public class TestPane extends JPanel {
private Timer timer = new Timer(25, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
add(new JButton("..."));
revalidate();
repaint();
}
});
public TestPane() {
JButton btn = new JButton("Help");
btn.getModel().addChangeListener(new ChangeListener() {
#Override
public void stateChanged(ChangeEvent e) {
ButtonModel model = (ButtonModel) e.getSource();
if (model.isPressed()) {
timer.start();
} else {
timer.stop();
}
}
});
add(btn);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
}
Thanks, this works if I press one Button. But if I press one Button and move the mouse with pressed mousebutton to another Button the secound button does nothing
Just so we're clear, I think this is a bad user experience, but that's me
public class Test {
public static void main(String[] args) {
new Test();
}
private boolean pressed = false;
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
add(makeButton("1"));
add(makeButton("2"));
}
protected JButton makeButton(String text) {
JButton btn = new JButton(text);
MouseAdapter ma = new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
pressed = true;
}
#Override
public void mouseReleased(MouseEvent e) {
pressed = false;
}
#Override
public void mouseEntered(MouseEvent e) {
if (pressed) {
JButton btn = (JButton) e.getComponent();
System.out.println("Entered " + btn.getText());
btn.doClick();
}
}
};
btn.addMouseListener(ma);
btn.addMouseMotionListener(ma);
return btn;
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
}
}
#npinti Now I can do an action for every button over which i hover with my mouse. But if I try to change the implementation, so that the action are only done, if the mouse is also clicked, the action only works if i press a button and over the same button again. `JButton b = new JButton();
if(a==1){
b.setBackground(Color.WHITE);
}else{
b.setBackground(Color.BLACK);
}
b.addActionListener( new ActionListener(){
public void actionPerformed( ActionEvent arg0 ) {
matrix.activate(x,y);
}
});
b.addMouseListener(new MouseListener() {
int pressed =0;
#Override
public void mouseReleased(MouseEvent e) {
pressed =0;
}
#Override
public void mousePressed(MouseEvent e) {
pressed =1;
}
#Override
public void mouseExited(MouseEvent e) {
}
#Override
public void mouseEntered(MouseEvent e) {
if (e.getComponent().equals(b) && pressed ==1){
b.setBackground(Color.BLACK);
}
}
public void mouseClicked(MouseEvent e) {
pressed =1;
}
});`
Catch mouseEntered on your buttons and if a global boolean pressed is true (set it to true when you press a mouse button and false on release), fire an action with JButton.doClick() which simulates a click event on the button.

KeyListener not responding to key inputs [duplicate]

This question already has an answer here:
Pong Paddle bottom doesn't move up when UP key is pressed
(1 answer)
Closed 7 years ago.
So I have seen a couple of these questions asked. They all say that you should not be using a Keylistener but instead a KeyBinding thing. But when I go to use the Keybinding it does not work. I understand I probably should be using the KeyBinding thing but is there a way that I can fix my code so that the KeyListener works. Thank you.
Game Class:
public class Game extends JFrame implements KeyListener{
public static int ppx,ppy;
public static void main(String[] args) {
JFrame frame = new JFrame("Game");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(500,600);
frame.add(new THIng());
frame.setVisible(true);
}
#Override
public void keyTyped(KeyEvent e) {
}
#Override
public void keyPressed(KeyEvent e) {
int keycode = e.getKeyCode();
if(keycode == KeyEvent.VK_D){
System.out.println("Debug");
}
}
#Override
public void keyReleased(KeyEvent e) {
}
}
THIng Class:
public class THIng extends JPanel{
public static int px,py,pwid,phei;
public void main(String[]args){
Timer timer;
timer = new Timer(60,
new ActionListener(){
public void actionPerformed(ActionEvent evt){
p();
}
}
);
}
public THIng(){
px = Game.ppx;py = Game.ppy;pwid = 50;phei = pwid;
}
#Override
public Dimension getPreferredSize(){
return new Dimension(500,600);
}
#Override
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics p = (Graphics)g;
p.drawRect(px,py,pwid,phei);
}
public void p(){
repaint();
}
}
you don't have to make a constructor, just add frame.addKeyListener(this); where you have set other properties of the JFrame.
as MadProgrammer has pointed out the right thing to do is use the Key Bindings API which you can see step by step Key Bindings API
add a constructor that adds a key listener and in your main make it class Game instead of JFrame
public class Game extends JFrame implements KeyListener{
public static int ppx,ppy;
public Game(String string) {
addKeyListener(this);
// TODO Auto-generated constructor stub
}
public static void main(String[] args) {
Game frame = new Game("Game");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(500,600);
frame.add(new THIng());
frame.setVisible(true);
}
#Override
public void keyTyped(KeyEvent e) {
}
#Override
public void keyPressed(KeyEvent e) {
int keycode = e.getKeyCode();
if(keycode == KeyEvent.VK_D){
System.out.println("Debug");
}
}
#Override
public void keyReleased(KeyEvent arg0) {
// TODO Auto-generated method stub
}
}

Why methods mouseExited and mouseEntered run together when I enter or exit JDialog?

Yes, this question is already posted on JavaRanch but I do not understand them well.
I have JDialog which has MouseListener added as follows:
super.addMouseListener(new MouseAdapter() {
#Override
public void mouseExited(MouseEvent e) {
if (e.getSource() instanceof ConnectionTreeTooltip) {
System.out.println("mouse exited!!!!!!!!!!!!!!!!!!=" + e);
// hideTooltip();
}
}
#Override
public void mouseEntered(MouseEvent e) {
if (e.getSource() instanceof ConnectionTreeTooltip) {
System.out.println("mouse entered!!!!!!!!!!!!!!!!!!=" + e);
// hideTooltip();
}
}
});
ConnectionTreeTooltip is this jdialog.
The problem is that both these two methods are invoked whenever mouse enters or exits JDialog. They merely run together.
The code of my JDialog:
public class ConnectionTreeTooltip extends JDialog {
...........
public ConnectionTreeTooltip(ConnectionsTree connectionsTree) {
super(connectionsTree.getMainFrame(), "", false);
super.setUndecorated(true);
super.setFocusableWindowState(false);
.............
super.getContentPane().add(scrollPane);
super.pack();
}
connectionsTree.getMainFrame() returns instance of JFrame.
EDIT Here is full code :
public ConnectionTreeTooltip(ConnectionsTree connectionsTree) {
super(connectionsTree.getMainFrame(), "", false);
super.setUndecorated(true);
super.setFocusableWindowState(false);
this.connectionsTree = connectionsTree;
JPanel contentPane = (JPanel) super.getContentPane();
contentPane.setBorder(BorderFactory.createEtchedBorder(EtchedBorder.LOWERED, Color.blue, Color.red));
tipLabel = new JLabel();
// by default, JLabel is not focusable.
tipLabel.setFocusable(true);
tipLabel.setBackground(Color.WHITE);
scrollPane = new JScrollPane(tipLabel) {
#Override
public Dimension getPreferredSize() {
return preferredSizeOfScrollPane;
}
};
scrollPane.setBorder(BorderFactory.createEmptyBorder(3, 3, 1, 1));
super.addMouseListener(new MouseAdapter() {
#Override
public void mouseExited(MouseEvent e) {
if (e.getSource() instanceof ConnectionTreeTooltip) {
System.out.println("mouse exited!!!!!!!!!!!!!!!!!!=" + e);
// hideTooltip();
}
}
#Override
public void mouseEntered(MouseEvent e) {
if (e.getSource() instanceof ConnectionTreeTooltip) {
System.out.println("mouse entered!!!!!!!!!!!!!!!!!!=" + e);
// hideTooltip();
}
}
});
tipLabel.addKeyListener(new KeyAdapter() {
#Override
public void keyReleased(KeyEvent e) {
// tipLabel can key events only if it is visible and focused
if (e.getKeyCode() == 32) {
unFocusTipLabel();
}
}
});
super.getContentPane().add(scrollPane);
super.pack();
}
Why is that and what is wrong with my JDialog or my MouseListener?
Thank you!
In all likelihood your JDialog holds a component inside of it that steals the mouse listener from the dialog itself, and so when your mouse enters the dialog, the dialog senses the mouse entering, but then the mouse immediately enters the dialog's component (the JScrollPane perhaps), the mouselistener senses that you've left the dialog and have entered its child component.
For example, my SSCCE:
import java.awt.event.*;
import javax.swing.*;
public class MouseListenerTest {
public static void main(String[] args) {
final JFrame mainFrame = new JFrame("My Frame");
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainFrame.add(new JPanel() {
{
add(new JButton(new AbstractAction("Show Dialog") {
#Override
public void actionPerformed(ActionEvent arg0) {
ConnectionTreeTooltip cttt = new ConnectionTreeTooltip(
mainFrame);
cttt.setVisible(true);
}
}));
}
});
mainFrame.pack();
mainFrame.setLocationRelativeTo(null);
mainFrame.setVisible(true);
}
}
class ConnectionTreeTooltip extends JDialog {
public ConnectionTreeTooltip(JFrame mainFrame) {
super(mainFrame, "", false);
setUndecorated(true);
setFocusableWindowState(false);
add(new JScrollPane(new JTextArea(20, 40)));
((JPanel)getContentPane()).setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4));
pack();
addMouseListener(new MouseAdapter() {
#Override
public void mouseExited(MouseEvent e) {
if (e.getSource() instanceof ConnectionTreeTooltip) {
System.out.println("mouse exited!!!!!!!!!!!!!!!!!!=" + e);
// hideTooltip();
}
}
#Override
public void mouseEntered(MouseEvent e) {
if (e.getSource() instanceof ConnectionTreeTooltip) {
System.out.println("mouse entered!!!!!!!!!!!!!!!!!!=" + e);
// hideTooltip();
}
}
});
}
}
now the tough part is to figure out how to use the GlassPane to get your Mouse enter/leaving information, but still allow the mouse events to be passed onto the dialog that's below the glass pane.
Edit
Yep the solution is to use the glass pane:
import java.awt.event.*;
import javax.swing.*;
public class MouseListenerTest {
public static void main(String[] args) {
final JFrame mainFrame = new JFrame("My Frame");
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainFrame.add(new JPanel() {
{
add(new JButton(new AbstractAction("Show Dialog") {
#Override
public void actionPerformed(ActionEvent arg0) {
ConnectionTreeTooltip cttt = new ConnectionTreeTooltip(
mainFrame);
cttt.setVisible(true);
}
}));
}
});
mainFrame.pack();
mainFrame.setLocationRelativeTo(null);
mainFrame.setVisible(true);
}
}
class ConnectionTreeTooltip extends JDialog {
public ConnectionTreeTooltip(JFrame mainFrame) {
super(mainFrame, "", false);
setUndecorated(true);
setFocusableWindowState(false);
add(new JScrollPane(new JTextArea(20, 40)));
((JPanel) getContentPane()).setBorder(
BorderFactory.createEmptyBorder(4, 4, 4, 4));
pack();
JComponent glassPane = (JComponent) getGlassPane();
glassPane.setVisible(true);
glassPane.addMouseListener(new MyMouseAdapter());
}
private class MyMouseAdapter extends MouseAdapter {
#Override
public void mouseExited(MouseEvent e) {
System.out.println("mouse exited");
}
#Override
public void mouseEntered(MouseEvent e) {
System.out.println("mouse entered");
}
}
}
I solved my problem in better way than using GlassPane. GlassPane only added more troubles to me because I could not scroll JScrollPane which is under GlassPane and redispatching mouse event suggested in glasspane swing tutorial did not help at all because mouseListener on glasspane did not receive mouseDragged.
The solution is by using AWTEventListener. With AWTEventListener I can check for component event is on and event's ID. So my AWTEventListener checks if mouseEntered event occurred over JDialog and if so it is focused programmatically. And if mouseDragged event occurred over JScrollPane I scroll it programmatically. Finally if mouseExited event occurred on JDialog it is hidden.
Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() {
#Override
public void eventDispatched(AWTEvent event) {
MouseEvent me = (MouseEvent) event;
Component mouseComponent = me.getComponent();
if (mouseComponent == scrollPane) {
if (me.getID() == MouseEvent.MOUSE_DRAGGED) {
scrollPane.getViewport().setViewPosition(me.getPoint()); // scroll JScrollPane programmatically
}
} else if (mouseComponent == ConnectionTreeTooltip.this) {
if (me.getID() == MouseEvent.MOUSE_ENTERED)
focusTipLabel(); //focus JDialog(ConnectionTreeTooltip)
else if (me.getID() == MouseEvent.MOUSE_EXITED) {
hideTooltip(); //hide JDialog(ConnectionTreeTooltip)
}
}
}
}, AWTEvent.MOUSE_EVENT_MASK);
But this AWTEventListener works for mouseevents generated from any component in my main frame. And it does not always handle mouseExited event on JDialog.
Or a simpler alternative. Check the coordinates of the mouse on the mouseExited and only count as an exit if the mouse is really outside the control:
super.addMouseListener(new MouseAdapter() {
#Override
public void mouseExited(MouseEvent e) {
Point cursor = e.getPoint();
if ( (cursor.x < super.getX()) || (cursor.y < super.getY()) || (cursor.x > popup.getX()+super.getWidth()) || (cursor.y > super.getY()+super.getHeight()))
popup.setVisible(false);
}
});

Categories