i'm making a keylistener that listens to ctrl-1 and ctrl-2.
Im making a quiz for teams. Team 1 should press ctrl-1 if they want to answer. Team 2 should press ctrl-2 if they want to answer.
The reason i chose for ctrl is because there are 2 control keys. So 2 teams can play against eachother on 1 keyboard.
I want team 1 to use the left control and the numbers under F1-F12.
And team 2 to use the right control and the numbers on the numlock.
My code registrates the triggers of team 1 but not from team 2.
Here is my code :
public void keyPressed(KeyEvent e) {
if((QuizController)getController() != null){
if(e.getKeyCode () == KeyEvent.VK_1){
if((e.getModifiers() & KeyEvent.CTRL_MASK) != 0)
System.out.println("Team 1");
}
if(e.getKeyCode () == KeyEvent.VK_2){
if((e.getModifiers() & KeyEvent.CTRL_MASK) != 0)
System.out.println("Team 2");
}
}
}
EDIT : I just did it with key bindings, gives the same problem, here is the code.
AbstractAction team1 = new AbstractAction() {
public void actionPerformed(ActionEvent arg0) {
System.out.println("Team 1");
}
};
AbstractAction team2 = new AbstractAction() {
#Override
public void actionPerformed(ActionEvent arg0) {
System.out.println("Team 2");
}
};
getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_1, java.awt.event.InputEvent.CTRL_DOWN_MASK),"actionMap1");
getActionMap().put("actionMap1", team1);
getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_2, java.awt.event.InputEvent.CTRL_DOWN_MASK),"actionMap2");
getActionMap().put("actionMap2", team2);
Thank you!
Firstly, I would highly recommend using the key bindings API.
Second KeyEvent.VK_1 is not the same event that is raised for numpad+1, this is triggered by KeyEvent.VK_NUMPAD1 instead, it's a different key event, just like the function keys are raise KeyEvent.VK_F1 to 12 events.
For example...
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class KeyBindingsTest {
public static void main(String[] args) {
new KeyBindingsTest();
}
public KeyBindingsTest() {
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 {
private JLabel state;
public TestPane() {
setLayout(new GridBagLayout());
state = new JLabel("Nothing here");
add(state);
InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_1, KeyEvent.CTRL_DOWN_MASK), "Ctrl+1");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_2, KeyEvent.CTRL_DOWN_MASK), "Ctrl+2");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_NUMPAD1, KeyEvent.CTRL_DOWN_MASK), "Ctrl+1");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_NUMPAD2, KeyEvent.CTRL_DOWN_MASK), "Ctrl+2");
ActionMap am = getActionMap();
am.put("Ctrl+1", new MessageAction("Ctrl+1"));
am.put("Ctrl+2", new MessageAction("Ctrl+2"));
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
public class MessageAction extends AbstractAction {
private String message;
public MessageAction(String message) {
this.message = message;
}
#Override
public void actionPerformed(ActionEvent e) {
state.setText(message);
}
}
}
}
Related
I was told in a project to especially differentiate keypresses between . and , from < and >. I saw a KeyEvent called KeyEvent.VK_GREATER and KeyEvent.VK_LESS but when I test it out through printing a string, nothing happens.
Please help :(
public void keyPressed(KeyEvent e)
{
boolean b = Utilities.isShiftDown(e);
switch (e.getKeyCode())
{
case KeyEvent.VK_Q:
System.exit(0);
break;
case KeyEvent.VK_LESS:
System.out.println("I'm Left");
break;
}
}
}
Sure it works for < and >
import java.awt.Dimension;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class KeyListenerTest extends JPanel {
public static void main(String[] args) {
SwingUtilities.invokeLater(()-> {
JFrame frame = new JFrame("Foo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new KeyListenerTest());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
});
}
public KeyListenerTest() {
setPreferredSize(new Dimension(400, 300));
setFocusable(true);
requestFocusInWindow();
addKeyListener(new KeyAdapter() {
#Override
public void keyPressed(KeyEvent e) {
super.keyPressed(e);
System.out.printf("Key id: %d; Key char: %c; key code: %d; Modifiers ex: %d%n",
e.getID(), e.getKeyChar(), e.getKeyCode(), e.getModifiersEx());
}
});
}
}
those keys return
Key id: 401; Key char: <; key code: 44; Modifiers ex: 64
Key id: 401; Key char: >; key code: 46; Modifiers ex: 64
These are the same key codes as common and period but with a non-0 modifiers ex of 64, consistent with the SHIFT_DOWN_MASK value for the modifierex, indicating that the shift key is pressed.
And to specifically test for greater than and less than, you'd check both key code and modifiers ex:
if (e.getKeyCode() == KeyEvent.VK_COMMA && (e.getModifiersEx() & KeyEvent.SHIFT_DOWN_MASK) != 0) {
System.out.println("LESS-THAN pressed");
}
if (e.getKeyCode() == KeyEvent.VK_PERIOD && (e.getModifiersEx() & KeyEvent.SHIFT_DOWN_MASK) != 0) {
System.out.println("GREATER-THAN pressed");
}
Key Bindings version of program:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.BorderFactory;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
#SuppressWarnings("serial")
public class KeyBindingTest extends JPanel {
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
JFrame frame = new JFrame("Foo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new KeyBindingTest());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
});
}
public KeyBindingTest() {
setPreferredSize(new Dimension(400, 300));
KeyStroke lessThanKeyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_COMMA, KeyEvent.SHIFT_DOWN_MASK);
KeyStroke greaterThanKeyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_PERIOD, KeyEvent.SHIFT_DOWN_MASK);
int condition = WHEN_IN_FOCUSED_WINDOW;
InputMap inputMap = getInputMap(condition);
ActionMap actionMap = getActionMap();
borderFlash(lessThanKeyStroke, inputMap, actionMap, Color.BLUE);
borderFlash(greaterThanKeyStroke, inputMap, actionMap, Color.RED);
}
private void borderFlash(KeyStroke ks, InputMap inputMap, ActionMap actionMap, Color color) {
KeyStroke press = KeyStroke.getKeyStroke(ks.getKeyCode(), ks.getModifiers(), false);
KeyStroke release = KeyStroke.getKeyStroke(ks.getKeyCode(), ks.getModifiers(), true);
inputMap.put(press, press.toString());
inputMap.put(release, release.toString());
actionMap.put(press.toString(), new BorderFlashAction(color, false));
actionMap.put(release.toString(), new BorderFlashAction(color, true));
}
private class BorderFlashAction extends AbstractAction {
private static final int THICKNESS = 20;
private Color color;
private boolean release;
public BorderFlashAction(Color color, boolean release) {
this.color = color;
this.release = release;
}
#Override
public void actionPerformed(ActionEvent e) {
if (release) {
setBorder(null);
} else {
setBorder(BorderFactory.createLineBorder(color, THICKNESS));
}
}
}
}
Well for something simple maybe use the KeyEvent#getKeyChar() method instead, like this:
if (e.isShiftDown()) {
switch (e.getKeyChar()) {
case 'Q':
System.out.println("EXITING!");
System.exit(0);
break;
case '<':
System.out.println("I'm Left");
break;
}
}
This question already has answers here:
Validation of text fields and contact no text field
(2 answers)
Closed 6 years ago.
So I just started reading about DocumentListeners and some other Action Listeners today but I can't get my JButton to revert to setEnabled(false) state when any of the text fields are empty. Is this something to do with the caret position or is there a proper way of reverting it to original state setEnabled(false) when any of the text fields are empty.
Here's what I've written so far.
public class home extends javax.swing.JPanel {
public home() {
JPasswordField currentPasswordJPasswordField;
JPasswordField newPasswordJPasswordField;
JPasswordField reTypeNewPasswordJPasswordField;
currentPasswordJPasswordField.getDocument().addDocumentListener(new textFieldListener(saveNewPasswordButton));
newPasswordJPasswordField.getDocument().addDocumentListener(new textFieldListener(saveNewPasswordButton));
reTypeNewPasswordJPasswordField.getDocument().addDocumentListener(new textFieldListener(saveNewPasswordButton));
}
public static class textFieldListener implements DocumentListener {
JButton btn;
public textFieldListener(JButton button) {
btn = button;
}
#Override
public void insertUpdate(DocumentEvent e) {
btn.setEnabled(true);
}
#Override
public void removeUpdate(DocumentEvent e) {
btn.setEnabled(true);
}
#Override
public void changedUpdate(DocumentEvent e) {
btn.setEnabled(true);
}
}
}
When I type something on the textfield it enables the save button as expected. But when I press backspace to clear all the text, save button won't revert to setEnabled(false).
I'd appreciate any response. I just started to learn this. I also want to know if I can put the action listeners in a separate .java file. If so, how can I apply the listeners to my main class.
Thanks.
Your basic approach is correct, using a DocumentListener, but you don't seem to be checking the length of the Document's contents at any point
This is a really simple example, but until all three fields have something in them, the button won't be enabled.
You could extend the idea by also checking to see if the first two fields match, but I'll leave that up to you
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.Document;
import javax.swing.text.JTextComponent;
public class Test {
public static void main(String[] args) {
new Test();
}
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 {
private JPasswordField currentPasswordJPasswordField;
private JPasswordField newPasswordJPasswordField;
private JPasswordField reTypeNewPasswordJPasswordField;
private List<JTextComponent> requiredFields = new ArrayList<>(25);
private JButton okay;
public TestPane() {
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.insets = new Insets(2, 2, 2, 2);
gbc.gridwidth = GridBagConstraints.REMAINDER;
currentPasswordJPasswordField = makePasswordField();
newPasswordJPasswordField = makePasswordField();
reTypeNewPasswordJPasswordField = makePasswordField();
add(currentPasswordJPasswordField, gbc);
add(newPasswordJPasswordField, gbc);
add(reTypeNewPasswordJPasswordField, gbc);
okay = new JButton("Ok");
add(okay);
updateState();
}
protected JPasswordField makePasswordField() {
JPasswordField field = new JPasswordField(20);
field.getDocument().addDocumentListener(new DocumentHandler());
requiredFields.add(field);
return field;
}
protected void updateState() {
boolean enabled = true;
for (JTextComponent field : requiredFields) {
if (field.getDocument().getLength() == 0) {
enabled = false;
break;
}
}
okay.setEnabled(enabled);
}
public class DocumentHandler implements DocumentListener {
#Override
public void insertUpdate(DocumentEvent e) {
updateState();
}
#Override
public void removeUpdate(DocumentEvent e) {
updateState();
}
#Override
public void changedUpdate(DocumentEvent e) {
updateState();
}
}
}
}
You can add a KeyListener to each of the text fields and update the button from inside the anonymous inner class.
currentPasswordJPasswordField.addKeyListener(new KeyAdapter() {
public void keyReleased(KeyEvent e) {
super.keyReleased(e);
if(currentPasswordJPasswordField.getText().length() > 0 &&
newPasswordJPasswordField.getText().length() > 0 &&
reTypeNewPasswordJPasswordField.getText().length() > 0) {
btn.setEnabeld(true);
} else {
btn.setEnabled(false);
}
}
});
newPasswordJPasswordField.addKeyListener(new KeyAdapter() {
public void keyReleased(KeyEvent e) {
super.keyReleased(e);
if(currentPasswordJPasswordField.getText().length() > 0 &&
newPasswordJPasswordField.getText().length() > 0 &&
reTypeNewPasswordJPasswordField.getText().length() > 0) {
btn.setEnabeld(true);
} else {
btn.setEnabled(false);
}
}
});
reTypeNewPasswordJPasswordField.addKeyListener(new KeyAdapter() {
public void keyReleased(KeyEvent e) {
super.keyReleased(e);
if(currentPasswordJPasswordField.getText().length() > 0 &&
newPasswordJPasswordField.getText().length() > 0 &&
reTypeNewPasswordJPasswordField.getText().length() > 0) {
btn.setEnabeld(true);
} else {
btn.setEnabled(false);
}
}
});
I need to send navigation commands using JButtons and the keyboard. If the "Up" button/up key is pressed I need to send "Move North" command, if up and left buttons are pressed(from keyboard), I need to send "Move North West" command etc.. The commands should be sent periodically(every 1 second). The following is the code I have.
To explain more,
There are three JButtons on the view. Let's call them jUp, jLeft and jRight. When the user presses the jUp button on the view, the program should send moveNorth commands periodically until the user releases the jUp button. When the user presses the up button on the keyboard, the same thing should happen, and the jUp button should look pressed until the user releases the keyboard up button. When the user presses the keyboard up and left buttons together, the jUp and jLeft buttons should appear pressed until user releases the keyboard buttons. And until user releases the keyboard buttons, a move northWest command should be sent periodically. In the code I have just printed the command using a System.out.println.
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.Timer;
public class ButtonDemo {
private JPanel buttons;
private Timer t;
private JButton upButton;
private JButton leftButton;
private JButton rightButton;
public static void main(String[] args) {
new ButtonDemo().run();
}
public ButtonDemo() {
buttons = new JPanel(new BorderLayout());
this.t = new Timer(1000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (upButton.isSelected() && leftButton.isSelected()) {
System.out.println("Move north west");
} else if (upButton.isSelected() && rightButton.isSelected()) {
System.out.println("Move north east");
} else if (upButton.isSelected()) {
System.out.println("Move north");
} else {
t.stop();
}
}
});
}
void run() {
this.upButton = new JButton("Up");
buttons.add(upButton, BorderLayout.NORTH);
setupButton(upButton, "Up", KeyEvent.VK_UP);
this.leftButton = new JButton("Left");
buttons.add(leftButton, BorderLayout.WEST);
setupButton(leftButton, "Left", KeyEvent.VK_LEFT);
this.rightButton = new JButton("Right");
buttons.add(rightButton, BorderLayout.EAST);
setupButton(rightButton, "Right", KeyEvent.VK_RIGHT);
JFrame frame = new JFrame("FrameDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(buttons, BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
}
private void setupButton(JButton button, String key, int vkUp) {
buttons.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(vkUp, 0),
key + " pressed");
buttons.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(vkUp, 0, true),
key + " released");
buttons.getActionMap().put(key + " pressed", new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
button.setSelected(true);
pressed(key);
}
});
buttons.getActionMap().put(key + " released", new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
button.setSelected(false);
}
});
}
private void pressed(String key) {
if (!t.isRunning()) {
t.start();
}
}
}
Now for the questions.
a) Even though I call the setSelected method, the button state does not change to pressed. (Visually it doesn't change to pressed state). How can I achieve this?
b) Is there a better/more standard way of achieving this functionality? Using mnemonics/ExecutorService etc..? Am I correct in adding the actions to the "buttons" element's input map. (Is buttons.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT) correct?) The panel will be in a tab and the buttons should work when that tab is selected.
JButton doesn't have a selected state, it has an armed. In order to have a button which maintain a "pressed" state when the mouse or key is released, you must use a JToggleButton.
I would, personally, move away from monitoring the button states, personally, and instead, use some kind enum or other constants which can be added and removed from a Set. This decouples the means by which the state is achieved from the process that is acting upon the state.
From there, you can use a single Action which would be used to notify some kind of observer that the state has changed
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.util.HashSet;
import java.util.Set;
import java.util.StringJoiner;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JToggleButton;
import javax.swing.KeyStroke;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
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 static class TestPane extends JPanel {
public enum Direction {
UP, DOWN, LEFT, RIGHT;
}
private JToggleButton[] buttons;
private Set keys;
private Timer timer;
private JLabel direction;
public TestPane() {
keys = new HashSet();
direction = new JLabel("Stopped");
timer = new Timer(1000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (keys.isEmpty()) {
((Timer) e.getSource()).stop();
direction.setText("Stopped");
} else {
StringJoiner joiner = new StringJoiner("-");
if (keys.contains(Direction.UP)) {
joiner.add("North");
}
if (keys.contains(Direction.DOWN)) {
joiner.add("South");
}
if (keys.contains(Direction.LEFT)) {
joiner.add("West");
}
if (keys.contains(Direction.RIGHT)) {
joiner.add("East");
}
direction.setText(joiner.toString());
}
}
});
Monitor monitor = new Monitor() {
#Override
public void pressed(Direction direction) {
keys.add(direction);
timer.restart();
}
#Override
public void released(Direction direction) {
keys.remove(direction);
}
};
MovementAction up = new MovementAction("Up", Direction.UP, monitor);
MovementAction down = new MovementAction("Down", Direction.DOWN, monitor);
MovementAction left = new MovementAction("Left", Direction.LEFT, monitor);
MovementAction right = new MovementAction("Right", Direction.RIGHT, monitor);
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridy = 0;
gbc.gridx = 1;
buttons = new JToggleButton[4];
buttons[0] = new JToggleButton(up);
buttons[1] = new JToggleButton(down);
buttons[2] = new JToggleButton(left);
buttons[3] = new JToggleButton(right);
add(buttons[0], gbc);
gbc.gridy = 2;
add(buttons[1], gbc);
gbc.gridy = 1;
gbc.gridx = 0;
add(buttons[2], gbc);
gbc.gridx++;
add(direction, gbc);
gbc.gridx++;
add(buttons[3], gbc);
addTriggerKeyBindingTo(buttons[0], KeyEvent.VK_UP, KeyEvent.VK_W, KeyEvent.VK_NUMPAD8);
addTriggerKeyBindingTo(buttons[1], KeyEvent.VK_DOWN, KeyEvent.VK_S, KeyEvent.VK_NUMPAD2);
addTriggerKeyBindingTo(buttons[2], KeyEvent.VK_LEFT, KeyEvent.VK_A, KeyEvent.VK_NUMPAD6);
addTriggerKeyBindingTo(buttons[3], KeyEvent.VK_RIGHT, KeyEvent.VK_D, KeyEvent.VK_NUMPAD4);
}
protected void addTriggerKeyBindingTo(JToggleButton comp, int... virtualKeys) {
InputMap im = comp.getInputMap(WHEN_IN_FOCUSED_WINDOW);
ActionMap am = comp.getActionMap();
for (int key : virtualKeys) {
im.put(KeyStroke.getKeyStroke(key, 0), "trigger");
}
am.put("trigger", new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
JToggleButton button = (JToggleButton) e.getSource();
button.doClick();
}
});
}
protected class MovementAction extends AbstractAction {
private Direction direction;
private Monitor monitor;
public MovementAction(String name, Direction direction, Monitor monitor) {
putValue(NAME, name);
this.direction = direction;
this.monitor = monitor;
putValue(SELECTED_KEY, false);
}
#Override
public void actionPerformed(ActionEvent e) {
boolean selected = (boolean) getValue(SELECTED_KEY);
if (selected) {
monitor.pressed(direction);
} else {
monitor.released(direction);
}
}
}
public interface Monitor {
public void pressed(Direction direction);
public void released(Direction direction);
}
}
}
Now, this example doesn't care, but you could use the Monitor to control which key/buttons where triggered at any one time, probably by returning a boolean value from pressed for example...
I have a very small question. Now I wrote the code for creating a virtual keyboard. I want the color of the button to change when it is typed. Here is my code:
public class ButtonColor implements KeyListener {
#Override
public void keyPressed(KeyEvent e) {
// TODO Auto-generated method stub
}
#Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
}
#Override
public void keyTyped(KeyEvent e) {
if (e.getKeyChar()=='a') {
A.setBackground(Color.red);
}
}
}
]
Whenever I press A, nothing happens. When I add this line:
JOptionPane.showMessageDialog(null, "A was typed");
then type a, the message appears and after I click OK the button changes color. Why does that happen? How can I fix this problem?
There could be any number of reasons why this doesn't work for you, for starters, the button may be transparent (opaque == false)
I would strongly recommend against KeyListener in favour of Key Bindings as KeyListener has issues with focus...
For example...
The following uses the key bindings API in order to respond to a given key stroke, depending on if it's a key press or release event, it will set the background color and opacity state accordingly and even sets the buttons pressed state...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class KeyboardTest {
public static void main(String[] args) {
new KeyboardTest();
}
public KeyboardTest() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
JButton btnA = createButton("A");
JButton btnB = createButton("B");
JButton btnC = createButton("C");
JButton btnD = createButton("D");
JButton btnE = createButton("E");
add(btnA);
add(btnB);
add(btnC);
add(btnD);
add(btnE);
addKeyBinding(btnA, "A", KeyEvent.VK_A);
addKeyBinding(btnB, "B", KeyEvent.VK_B);
addKeyBinding(btnC, "C", KeyEvent.VK_C);
addKeyBinding(btnD, "D", KeyEvent.VK_D);
addKeyBinding(btnE, "E", KeyEvent.VK_E);
}
protected JButton createButton(String text) {
JButton btn = new JButton(text);
btn.setFocusable(false);
return btn;
}
protected void addKeyBinding(JButton btn, String name, int virtualKey) {
ActionMap am = getActionMap();
InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
im.put(KeyStroke.getKeyStroke(virtualKey, 0, false), name + ".pressed");
im.put(KeyStroke.getKeyStroke(virtualKey, 0, true), name + ".released");
am.put(name + ".pressed", new KeyAction(btn, true));
am.put(name + ".released", new KeyAction(btn, false));
}
}
public class KeyAction extends AbstractAction {
private JButton btn;
private boolean highlight;
public KeyAction(JButton btn, boolean highlight) {
this.btn = btn;
this.highlight = highlight;
}
#Override
public void actionPerformed(ActionEvent e) {
if (highlight) {
btn.getModel().setPressed(true);
btn.setBackground(Color.RED);
btn.setOpaque(true);
} else {
btn.getModel().setPressed(false);
btn.setBackground(null);
btn.setOpaque(false);
}
}
}
}
Updated
If you also use btn.getModel().setArmed(...); you will get a much more "bolded" response, which produces better visual feedback...IMHO
How would I go about closing a JFrame after user inactivity?
So far I have,
Thread.sleep(10000);
I would greatly appreciate it if someone could give me code to do this?
I am new to Java and want to know more about system security
This is an example of Braj's idea using a javax.swing.Timer.
It simplifies the process, as you don't need to monitor the time between events and ensures that when the timer is triggered, the event occurs within the Event Dispatching Thread, further reducing the complexity.
Also note that I included the AWTEvent.MOUSE_MOTION_EVENT_MASK and AWTEvent.MOUSE_WHEEL_EVENT_MASK events for good measure ;)
import java.awt.AWTEvent;
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.Toolkit;
import java.awt.Window;
import java.awt.event.AWTEventListener;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class AutoClose {
public static void main(String[] args) {
new AutoClose();
}
private Timer timer;
private JLabel label;
private JFrame frame;
public AutoClose() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
label = new JLabel("Waiting...");
frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(label);
frame.setSize(200, 200);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() {
private int count;
#Override
public void eventDispatched(AWTEvent event) {
Object source = event.getSource();
if (source instanceof Component) {
Component comp = (Component) source;
Window win = null;
if (comp instanceof Window) {
win = (Window) comp;
} else {
win = SwingUtilities.windowForComponent(comp);
}
if (win == frame) {
timer.restart();
label.setText("Interrupted..." + (++count));
}
}
}
}, AWTEvent.KEY_EVENT_MASK | AWTEvent.MOUSE_EVENT_MASK | AWTEvent.MOUSE_MOTION_EVENT_MASK | AWTEvent.MOUSE_WHEEL_EVENT_MASK);
timer = new Timer(5000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
frame.dispose();
}
});
// You could use a WindowListener to start this
timer.start();
}
});
}
}
Try this one
Steps to follow:
Its listening for key event as well as mouse event.
A new thread is started that will check.
If the time difference is more than specified time (10 sec in below sample code) then dispose the window.
That's all.
Here is the sample code:
private long time;
...
long eventMask = AWTEvent.KEY_EVENT_MASK | AWTEvent.MOUSE_EVENT_MASK;
Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() {
public void eventDispatched(AWTEvent e) {
time = System.currentTimeMillis();
}
}, eventMask);
time = System.currentTimeMillis();
new Thread(new Runnable() {
#Override
public void run() {
while (true) {
if (System.currentTimeMillis() - time > 10000) {
widnow.dispose();
break;
}
}
}
}).start();