Issue
I have a jframe of which I have made in Netbeans, this jframe is being "launched" by another java class, but for the current question that doesn't matter. What matters is the fact that I can't seem to figure out how to add my key listener to this jframe of mine. I have implemented the key listener, added the required functions (key typed, key pressed and key released). But I can't figure out how to actually add/initiate the actual key listener, to make it work.
As of right now I have tried two different things, first I have tried to add the line addKeylistener(new JFrameList());
in the start of the code, where the actual jframe is being initiated, but doing so the actual frame won't even show. Apart from this I have tried to add the same line within another function callJframFForm()
, which is called from another class at the same time as the jframe is called. But this just returns the error non-static method addKeyListener(KeyListener) cannot be referenced from a static context
. I am not sure what other ways I could add the key listener and thus am looking for a little help.
Currently my code looks like the one below.
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
public class JFrameList extends javax.swing.JFrame implements KeyListener{
public static String keyPresCod = "";
public JFrameList() {
initComponents();
addKeyListener(new JFrameList()); //This is where I am currently trying to call from, but frame won't show
}
public static void main(String args[]) {
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new JFrameList().setVisible(true);
}
});
}
// Variables declaration - do not modify
private javax.swing.JButton jButton1;
private javax.swing.JButton jButton2;
private javax.swing.JLabel jLabel1;
private javax.swing.JLabel jLabel2;
// End of variables declaration
static void callJframFForm(){
try {
//This is where I have also tried to add the initialization line
} catch(Exception e) {
e.printStackTrace();
}
}
@Override
public void keyTyped(KeyEvent e) {
int codeFKey = e.getKeyCode();
if (codeFKey == KeyEvent.VK_A) {
System.out.println("Button A clicked");
keyPresCod = "A";
} else if (codeFKey == KeyEvent.VK_B) {
System.out.println("Button B clicked");
keyPresCod = "B";
} else {
System.out.println("Different key pressed");
keyPresCod = "Another key";
}
}
@Override
public void keyPressed(KeyEvent e) {
}
@Override
public void keyReleased(KeyEvent e) {
}
}
Solution
Problem
addKeyListener(new JFrameList())
This creates a new JFrameList
object and uses it's listener. This means any keystrokes are being stored in the new object's member. To see the results, you would have to do
JFrameList list = new JFrameList(); addKeyListener(list); //use list variable to access keyPressed code
Of course this isn't the behavior you want. You want the keys strokes to be stored in the current instance, not a new object. This means you should be doing
addKeyListener(this)
Although you may notice the listener only works "sometimes", or maybe not at all depending on how you're testing it.
Swing uses a focus system to manage which listeners should be receiving events, and since you are adding the listener to a JFrame
, the listener will receive events only when the frame is in focus.
Solution
You should use key bindings rather than a key listener.
If you choose to continue using the listener, you should add it to your buttons, not your frame:
jButton1.addKeyListener(this);
jButton2.addKeyListener(this);
Instead of checking the key code of the event, you could grab the source of the event (your button) by calling event.getSource()
.
Key bindings allows you to set flexible focus settings for your components. All you need to do is access the input map of the component:
String actionCommand = "Press Button A";
jButton1.setActionCommand(actionCommand);
jButton1.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("A"), actionCommand);
jButton1.getActionMap(actionCommand, this);
Your JFrameList
should now implement ActionListener
rather than KeyListener
, as it will be receiving your events as actions:
class JFrameList extends JFrame implements ActionListener {
private JButton jButton1;
public JFrameList() {
jButton1 = new JButton("A");
//set action command, add to input map, add to action map
}
public void actionPerformed(ActionEvent event) {
JButton button = (JButton) event.getSource();
System.out.println(button.getActionCommand() + " was performed.");
}
}
Alternative
JButton
has built-in mnemonic handling. You can specify a mnemonic via JButton#setMnemonic(int)
, where the argument is a key code:
jButton1.setMnemonic(KeyEvent.VK_A);
This is the standard way of handling hotkeys in graphical interfaces. Simply hold down the Alt key (windows) then press the key you set the mnemonic to.
Answered By - Vince
Answer Checked By - Candace Johnson (JavaFixing Volunteer)