Avoid multiple key pressing: choose only one - java

In my ULC frame, I implemented some F hotkeys (from F1 to F12).
But there can be a little bug, for example if you want to press quickly the F10, maybe you press it with F11 also. I would like to avoid it somehow. Because now it will run both actions for these two keys.
What could be the best solution, if someone press two registered keys, but run only one from them. If this one is the first or the last, it does not matter.
I have tried with synchronized keyword, but it does not help, both command will be executed.
First code example (inner synchronized (parent)):
Button buttonFirst = createButton("F10");
buttonFirst.addActionListener(new IActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
synchronized (parent) {
System.out.println("F10 - pressed");
doSomething(1);
}
}
});
buttonFirst.addActionKeyStroke(KeyStroke.getKeyStroke(KeyEvent.VK_F10, 0, true));
Button buttonSecond = createButton("F11");
buttonSecond.addActionListener(new IActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
synchronized (parent) {
System.out.println("F11 - pressed");
doSomething(2);
}
}
});
buttonSecond.addActionKeyStroke(KeyStroke.getKeyStroke(KeyEvent.VK_F11, 0, true));
Second code example (outter synchronized method):
Button buttonFirst = createButton("F10");
buttonFirst.addActionListener(new IActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
doSomething("F10",1);
}
});
buttonFirst.addActionKeyStroke(KeyStroke.getKeyStroke(KeyEvent.VK_F10, 0, true));
Button buttonSecond = createButton("F11");
buttonSecond.addActionListener(new IActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
doSomething("F11",2);
}
});
buttonSecond.addActionKeyStroke(KeyStroke.getKeyStroke(KeyEvent.VK_F11, 0, true));
private synchronized void doSomething(String keyName, int value) {
System.out.println(keyName+" - pressed");
doSomething(value);
}

Related

How to assign a method to a button when pressed or released with ActionListener in Java?

I am new to coding GUIs in Java and I am trying to just print a message on the terminal when a button is pressed and another one when it is released.
This is what I have for a regular button pressing.
leftButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent actionEvent) {
System.out.println("Pressed");
}
});
I did this with the help of IntelliJ IDEA. I want to make the button send a message when pressed and a different thing when released.
You can just add a simple MouseAdapter, like this:
MouseAdapter ma = new MouseAdapter() {
public void mousePressed(MouseEvent e) {
System.out.println("Pressed");
}
public void mouseReleased(MouseEvent e) {
System.out.println("Released");
}
};
leftButton.addMouseListener(ma);
frame.add(button);
This will detect when it is the mouse is pressed on the button or released on the button.
If you want, you can also add a mouseClicked() method, mouseExited(), mouseEntered(), mouseMoved(), and (many) more methods in your MouseAdapter. Check out this JavaDoc
Use custom class and use it
leftButton.getModel().addChangeListener(new BtnCusttomListener());
private class BtnCusttomListener implements ChangeListener {
private boolean pressed = false; // holds the last pressed state of the button
#Override
public void stateChanged(ChangeEvent e) {
ButtonModel Buttonmodel = (ButtonModel) e.getSource();
// if the current state differs from the previous state
if (model.isPressed() != pressed) {
String text = "Button pressed: " + model.isPressed() + "\n";
textArea.append(text);
pressed = model.isPressed();
}
}
}
You can use a MouseListener instead:
leftButton.addMouseListener(new MouseListener() {
#Override
public void mouseClicked(MouseEvent e) {
// The mouse button was pressed and released
}
#Override
public void mousePressed(MouseEvent e) {
// The mouse button was pressed
}
#Override
public void mouseReleased(MouseEvent e) {
// The mouse button was released
}
#Override
public void mouseEntered(MouseEvent e) {
// The cursor entered the bounds of the button (i.e. hovering)
}
#Override
public void mouseExited(MouseEvent e) {
// The cursor exited the bounds of the button
}
});

JButton not invoking actionPerformed on any subsequent click in same GUI instance

I have a JButton that will not allow me to perform the same action on any subsequent click on it after the first in the same Swing GUI instance.
JButton Run = new JButton("Run");
Run.setLocation(290, 70);
Run.setSize(120, 30);
buttonPanel.add(Run);
Run.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (Run.isEnabled()) {
errorLabel.setText("");
Result result = JUnitCore.runClasses(Run.class);
errorMessageDisplay(result);
}
}
});
totalGUI.setOpaque(true);
return totalGUI;
}
So far I thought about and tried removing the JPanel and painting all of the buttons back on, and disabling/renabling buttons.
The errorMessageDisplay method is as follows:
public void errorMessageDisplay(Result resultPass) {
if (resultPass.getFailureCount() > 0) {
errorLabel.setForeground(Color.red);
errorLabel.setVisible(true);
errorLabel.setText(" Failed");
}
else {
errorLabel.setForeground(Color.green);
errorLabel.setText(" Passed");
errorLabel.setVisible(true);
}
}
At first glance, the JUnitCore.runClasses(Run.class); call is suspicous. Also, it would be good to know what does the errorMessageDisplay() do. I believe, the problem is with one of these methods.
You can verify this with the following experimental code. Just be careful not to push it into production.
JButton run = new JButton("Run");
run.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (Run.isEnabled()) {
errorLabel.setText("");
System.out.println("Run action peformed.");
}
}
Update Since the errorMessageDisplay() looks okay, it's probably a Threading problem with JUniCore. Thus I'd try the following code:
final ExecutorService executor = Executors.newFixedThreadPool(5); // this runs stuff in background
JButton run = new JButton("Run");
// ..
run.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (Run.isEnabled()) {
executor.execute(new Runnable() { // This is how we run stuff in background. You can use lambdas instead of Runnables.
public void run() {
final Result result = JUnitCore.runClasses(Run.class); // Run.class is different from the current JButton run.
SwingUtilities.invokeLater(new Runnable() { // Now we go back to the GUI thread
public void run() {
errorMessageDisplay(result);
}
});
}
});
}
});

Java - KeyListener not Working/Mouse Position Not Read

So I have a button that when pressed needs to write the current mouse position out to a text box until the user presses shift, then it stops and leaves the most recent mouse position as the final text in the text box. Heres what I have done:
First a created the following class.
public class KeyListener extends KeyAdapter {
private boolean wasPressed = false;
private int keyCode;
public KeyListener(int keyCode) {
this.keyCode = keyCode;
}
#Override
public void keyReleased(KeyEvent e) {
System.out.println("CALLED");
if(e.getKeyCode() == keyCode)
wasPressed = true;
}
public void setState(boolean state) {
wasPressed = state;
}
public boolean getState() {
return wasPressed;
}
}
Then in my "main" class I have the following code.
JButton track1 = new JButton("Track");
KeyListener kl = new KeyListener(KeyEvent.VK_SHIFT);
...
public DisplayFrame() {
this.addKeyListener(kl);
track1.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent event) {
kl.setState(false);
while(!kl.getState()) {
Point p = MouseInfo.getPointerInfo().getLocation();
topLeft.setText(p.getX() + "," + p.getY());
}
}
});
}
I then of course added the text box to a JPanel and it's displaying everything correctly, however, when I click the Track button nothing happens. I can tell that it is entering the loop, but no text is displayed in the textbox and pressing shift doesn't break the loop.
Try to make a new thread within the actionPerformed method like this:
Thread exampleThread = new Thread() {
public void run() {
//Do your actions within the new thread
}
};
//After the thread is made, we start it.
exampleThread.start();
You have to do this because the actionListener runs in a different thread.

Java - Want getKeyCode to only register once

I'm currently working on a little game. I'm using getKeyCode to move my character but the thing is that I don't want you to be able to keep moving if you hold in the button. Is there anyway I can use getKeyCode to only register on the first click and then won't register until I release the button and press again?
else if (event.getKeyCode()== KeyEvent.VK_UP)
{
spelare1.setLocation(spelare1.getX(),spelare1.getY()-50);
}
This is how it currently looks like.
I think you are confusing KeyEvents. VK_UP is the up arrow key. Use KeyEvent.KEY_RELEASED to react on a released key.
You can keep a boolean indicating whether the key is currently pressed. Then you can react once after each press, like in this example:
public static void main(String[] args) {
JFrame f = new JFrame();
f.addKeyListener(new KeyAdapter() {
private boolean pressed;
#Override
public void keyReleased(KeyEvent e) {
pressed = false;
}
#Override
public void keyPressed(KeyEvent e) {
if (!pressed) {
System.out.println("Key pressed: " + e.getKeyCode());
pressed = true;
}
}
});
SwingUtilities.invokeLater(new Runnable() {
public void run() {
f.setVisible(true);
}
});
}
Depending on your needs, you might want to have a separate state for each key, or just one shared state.

How to select all text in a JFormattedTextField when it gets focus?

I have a small Java desktop app that uses Swing. There is a data entry dialog with some input fields of different types (JTextField, JComboBox, JSpinner, JFormattedTextField). When I activate the JFormattedTextFields either by tabbing through the form or by clicking it with the mouse, I would like it to select all the text that it currently contains. That way, users could just start typing and overwrite the default values.
How can I do that? I did use a FocusListener/FocusAdapter that calls selectAll() on the JFormattedTextField, but it doesn't select anything, although the FocusAdapter's focusGained() method is called (see code sample below).
private javax.swing.JFormattedTextField pricePerLiter;
// ...
pricePerLiter.setFormatterFactory(
new JFormattedTextField.AbstractFormatterFactory() {
private NumberFormatter formatter = null;
public JFormattedTextField.AbstractFormatter
getFormatter(JFormattedTextField jft) {
if (formatter == null) {
formatter = new NumberFormatter(new DecimalFormat("#0.000"));
formatter.setValueClass(Double.class);
}
return formatter;
}
});
// ...
pricePerLiter.addFocusListener(new java.awt.event.FocusAdapter() {
public void focusGained(java.awt.event.FocusEvent evt) {
pricePerLiter.selectAll();
}
});
Any ideas? The funny thing is that selecting all of its text apparently is the default behavior for both JTextField and JSpinner, at least when tabbing through the form.
Wrap your call with SwingUtilities.invokeLater so it will happen after all pending AWT events have been processed :
pricePerLiter.addFocusListener(new java.awt.event.FocusAdapter() {
public void focusGained(java.awt.event.FocusEvent evt) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
pricePerLiter.selectAll();
}
});
}
});
In addition to the above, if you want this for all text fields you can just do:
KeyboardFocusManager.getCurrentKeyboardFocusManager()
.addPropertyChangeListener("permanentFocusOwner", new PropertyChangeListener()
{
public void propertyChange(final PropertyChangeEvent e)
{
if (e.getNewValue() instanceof JTextField)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
JTextField textField = (JTextField)e.getNewValue();
textField.selectAll();
}
});
}
}
});
Thats because the JFormattedTextfield overrides processFocusEvent to format on focus gained/focus lost.
One sure shot way is to extend JFormattedTextField and override the processFocusEvent method :
new JFormattedTextField("...") {
protected void processFocusEvent(FocusEvent e) {
super.processFocusEvent(e);
if (e.isTemporary())
return;
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
selectAll();
}
});
}
};
Using a focusListener might not always work..since it would depend on the time at which it is called relative to the processFocusEvent.
I know this is kind of old, but I came up with a cleaner solution, without invokeLater:
private class SelectAllOfFocus extends FocusAdapter {
#Override
public void focusGained(FocusEvent e) {
if (! e.isTemporary()) {
JFormattedTextField textField = (JFormattedTextField)e.getComponent();
// This is needed to put the text field in edited mode, so that its processFocusEvent doesn't
// do anything. Otherwise, it calls setValue, and the selection is lost.
textField.setText(textField.getText());
textField.selectAll();
}
}
}
The code of camickr can be slightly improved. When the focus passes from a JTextField to another kind of component (such a button), the last automatic selection does not get cleared. It can be fixed this way:
KeyboardFocusManager.getCurrentKeyboardFocusManager()
.addPropertyChangeListener("permanentFocusOwner", new PropertyChangeListener()
{
#Override
public void propertyChange(final PropertyChangeEvent e)
{
if (e.getOldValue() instanceof JTextField)
{
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
JTextField oldTextField = (JTextField)e.getOldValue();
oldTextField.setSelectionStart(0);
oldTextField.setSelectionEnd(0);
}
});
}
if (e.getNewValue() instanceof JTextField)
{
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
JTextField textField = (JTextField)e.getNewValue();
textField.selectAll();
}
});
}
}
});

Categories