I'm creating a java swing application. The window has several buttons, and I would like the user to use the tab key to switch between buttons, and then press enter to activate the selected button.
I've created a sample window below. It has two buttons and a label, and activating either button changes the text of the label.
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.UIManager;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
public class ButtonTest
{
private JFrame frame;
// Create the application.
public ButtonTest() { initialize(); }
// Initialize the contents of the frame.
private void initialize()
{
frame = new JFrame();
frame.setBounds(100, 100, 450, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(null);
JLabel lblText = new JLabel("Text");
lblText.setBounds(167, 59, 46, 14);
frame.getContentPane().add(lblText);
JButton btnRed = new JButton("Red");
btnRed.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
lblText.setText("Red");
}
});
btnRed.setBounds(74, 174, 89, 23);
frame.getContentPane().add(btnRed);
JButton btnBlue = new JButton("Blue");
btnBlue.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
lblText.setText("Blue");
}
});
btnBlue.setBounds(220, 174, 89, 23);
frame.getContentPane().add(btnBlue);
}
// Launch the application.
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
try
{
ButtonTest window = new ButtonTest();
window.frame.setVisible(true);
} catch (Exception e)
{
e.printStackTrace();
}
}
});
}
}
When I run this code, I can press tab to switch between buttons, and pressing space while one of the buttons is focused activates it. I would prefer to press enter instead of space to activate the focused button. I've seen other answers on this site that use the following line of code to fix this issue:
UIManager.put("Button.defaultButtonFollowsFocus", Boolean.TRUE);
This works on Windows, but it doesn't seem to work on Macs. On Macs, pressing space still works, and pressing enter still does nothing. Is there a solution that works on both platforms? (Note: to run this application on a Mac, I first export it to a runnable jar file.)
You can use Key Bindings to bind the existing Action to a different KeyStroke for a single button:
InputMap im = button.getInputMap();
im.put( KeyStroke.getKeyStroke( "ENTER" ), "pressed" );
im.put( KeyStroke.getKeyStroke( "released ENTER" ), "released" );
or for all buttons in your application.
InputMap im = (InputMap)UIManager.get("Button.focusInputMap");
im.put( KeyStroke.getKeyStroke( "ENTER" ), "pressed" );
im.put( KeyStroke.getKeyStroke( "released ENTER" ), "released" );
See: Enter Key and Button for more information.
Related
I'm new to windowbuilder designer with eclipse. I'm using eclipse 2021-12, jdk 17 and windowbuilder 1.9.8 version.
I'm trying to add an actionListener on a button in design mode. But when I double-click on this button in design mode, to add an actionListener, nothing happens.
Here is my source code in source mode :
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JButton;
import java.awt.Font;
import java.awt.Color;
public class SwingApp {
private JFrame frame;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
SwingApp window = new SwingApp();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public SwingApp() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 450, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(null);
JButton btnClick = new JButton("Click");
btnClick.setBackground(new Color(219, 112, 147));
btnClick.setForeground(new Color(255, 255, 255));
btnClick.setFont(new Font("Inconsolata SemiBold", Font.BOLD, 14));
btnClick.setBounds(165, 101, 118, 51);
frame.getContentPane().add(btnClick);
}
}
And here is the rendering in design mode : the rendering in design mode
Righ-click on the button and add an event handler. You want to add a mouse event handler.
I am new to Java and I'm trying to make an auto clicker. It works like this. when you click a button, the application starts clicking (also works when you press s), and when you press "w" the application stops clicking. My main issue currently is I can't manage to make my application click :V. (I also have a "main.java" for startup) Here's my code vvvvvvv
package copy;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.KeyAdapter;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Game
implements ActionListener{
JFrame frame;
JLabel label;
JButton button;
Action ON;
Action OFF;
private static Robot bot;
public static boolean status = false;
Game(){
ON = new statusON();
OFF = new statusOFF();
frame = new JFrame("Bullet Chicken Clicker");
label = new JLabel();
button = new JButton("turn on?");
frame.setSize(400, 400);
frame.setLocation(600, 150);
frame.setVisible(true);
frame.setAlwaysOnTop(true);
frame.add(label);
frame.add(button);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
label.getInputMap().put(KeyStroke.getKeyStroke('w'), "OFF");
label.getActionMap().put("OFF", OFF);
label.getInputMap().put(KeyStroke.getKeyStroke('w'), "upAction");
label.getActionMap().put("upAction", ON);
label.getInputMap().put(KeyStroke.getKeyStroke('s'), "downAction");
label.getActionMap().put("downAction", OFF);
button.setPreferredSize(new Dimension(40, 40));
button.setOpaque(true);
button.setForeground(Color.BLACK);
button.setBounds(125, 150, 150, 30);
button.setVisible(true);
button.addActionListener(this);
button.setFocusable(false);
}
private void clicky() {
while (status == true);
bot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
bot.delay(300);
bot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
bot.delay(300);
}
public static void robot() {
try {
bot = new Robot();
} catch (AWTException e2) {
e2.printStackTrace();
}
}
public class statusON extends AbstractAction{
#Override
public void actionPerformed(ActionEvent e) {
status = true;
System.out.print(status);
}
}
public class statusOFF extends AbstractAction{
#Override
public void actionPerformed(ActionEvent e) {
status = false;
System.out.print(status);
}
}
#Override
public void actionPerformed(ActionEvent e) {
status = true;
System.out.print(status);
}
}
My main issue currently is I can't manage to make my application click :V.
Well, you don't assign a key binding to the "V" key. You define the binding for "W" twice.
Having said that your code is still incorrect and will cause you problems in the future:
you are adding two components to the BorderLayout.CENTER
components should be added to the frame BEFORE the frame is made visible
you are using the wrong InputMap
From the tutorial given to you in your last question there are 3 InputMaps. The default InputMap will only work when the component has focus. In your incorrect example is just happens that the label does have focus. However, if you add more components it will likely not retain focus.
In the case of a game the easiest way to make sure you game responds to the KeyStroke is to bind the KeyStroke to the InputMap of the JRootPane of the frame. Then it doesn't matter which component on the frame has focus, the Action will be invoked.
So your code should be something like:
JRootPane rootPane = frame.getRootPane();
InputMap im = rootPane.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
im.put(KeyStroke.getKeyStroke('v'), "OFF");
rootPane.getActionMap().put("OFF", OFF);
im.put(KeyStroke.getKeyStroke('w'), "upAction");
rootPane.getActionMap().put("upAction", ON);
im.put(KeyStroke.getKeyStroke('s'), "downAction");
rootPane.getActionMap().put("downAction", OFF);
There is no need for the JLabel.
I'm fairly new to Java, and I have totally self taught my self to this point.
Right now I am trying to add a KeyListener to my JFrame class, I have no idea what I'm doing wrong and need some help. Any other tips are welcome.
My JFrame class:
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.*;
public class TestJavaFrame implements ActionListener, KeyListener {
private static JFrame frame = new JFrame();
// Componenets
JLabel timeinmslabel = new JLabel("Enter the time in miliseconds:");
JTextField timeinms = new JTextField();
JRadioButton checkBox = new JRadioButton();
JRadioButton checkBox2 = new JRadioButton();
private boolean amountoftimes = false;
public TestJavaFrame(String windowname) {
frame.setName(windowname);
frame.setResizable(true);
frame.setSize(900, 500);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocation(150, 50);
// JPanel
JPanel panel = new JPanel();
panel.setLayout(null);
panel.setBounds(frame.getBounds());
// Bounds for components
timeinmslabel.setBounds((int) (frame.getBounds().getX() / 2), 125, 200, 25);
timeinms.setBounds((int) (frame.getBounds().getX() / 2 + 185), 125, 200, 25);
checkBox.setBounds((int) (frame.getBounds().getX() / 2 + 185), 40, 200, 25);
checkBox2.setBounds((int) (frame.getBounds().getX() / 2 + 185), 70, 200, 25);
// Action Listeners
checkBox.addActionListener(this);
frame.addKeyListener(this);
// edit components
checkBox.setText("Use clicked amount of times.");
// add components
panel.add(timeinmslabel);
panel.add(timeinms);
panel.add(checkBox);
panel.add(checkBox2);
frame.add(panel);
frame.setVisible(true);
}
public void actionPerformed(ActionEvent e) {
System.out.println(e);
}
#Override
public void keyPressed(KeyEvent e) {
System.out.println(e.getKeyChar());
}
#Override
public void keyReleased(KeyEvent e) {
System.out.println(e.getKeyChar());
}
#Override
public void keyTyped(KeyEvent e) {
System.out.println(e.getKeyChar());
}
}
If you need my main, I'm perfectly fine with posting it, all it does right now is create this gui though.
So when the user hits the specific key it stops the auto clicker
Yes you can add the Key Binding to the panel.
A better approach is to create a menu bar for the various Actions support by your application. Then you can have menu items to start/stop the clicker. When you create the menu items you can then assign an accelerator to the menu item and the menu item will create the key bindings for you automatically.
This is a better solution because the "key binding" is self documenting since it is part of the menu item.
Read the section from the Swing tutorial on How to Use Menus for more information and working examples to get you started.
as I said I'm trying to learn here.
Keep a link to the tutorial handy for all Swing basics. There are also sections on "Key Bindings" and "How to Use Actions".
I'm wondering if its possible to make a button in JButton Press a key?
So for example If I have a button titled New Button, and I click it with the mouse. I want it to press my left arrow key.
Also is it possible to make it so that it keeps pressing it until I let go of the mouse? So more or less I click it and It presses my left arrow key continuously until I release the mouse then it stops?
I click it and It presses my left arrow key continuously until I release the mouse then it stops?
What is the point of this?
If you use the keyboard to press the left arrow, the KeyStroke is dispatched to the component that has focus. So if focus is on a text field, the left arrow will move the caret back one character.
If you click on a button, focus is now on the button and if you dispatch the left arrow to the button nothing will happen.
Maybe you are trying to use the left arrow key to do some kind of animation. If so, then you need to create an Action. Then you need to add code so that a button click or the pressing of the left arrow key can invoke this Action.
For the basic concepts of this approach you can read the Swing Tutorial. There are sections on:
How to Use Actions
How to Use Key Bindings
For a working example of this approach you can check out Motion Using the Keyboard. The MotionWithKeyBindings.java code does animation using the keyboard or the button.
Are you trying to do something like this? Here is a simple "Calculator" keyboard:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
public class CalculatorPanel extends JPanel
{
private JTextField display;
public CalculatorPanel()
{
Action numberAction = new AbstractAction()
{
#Override
public void actionPerformed(ActionEvent e)
{
// display.setCaretPosition( display.getDocument().getLength() );
display.replaceSelection(e.getActionCommand());
}
};
setLayout( new BorderLayout() );
display = new JTextField();
display.setEditable( false );
display.setHorizontalAlignment(JTextField.RIGHT);
add(display, BorderLayout.NORTH);
JPanel buttonPanel = new JPanel();
buttonPanel.setLayout( new GridLayout(0, 5) );
add(buttonPanel, BorderLayout.CENTER);
for (int i = 0; i < 10; i++)
{
String text = String.valueOf(i);
JButton button = new JButton( text );
button.addActionListener( numberAction );
button.setBorder( new LineBorder(Color.BLACK) );
button.setPreferredSize( new Dimension(50, 50) );
buttonPanel.add( button );
InputMap inputMap = button.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
inputMap.put(KeyStroke.getKeyStroke(text), text);
inputMap.put(KeyStroke.getKeyStroke("NUMPAD" + text), text);
button.getActionMap().put(text, numberAction);
}
}
private static void createAndShowUI()
{
// UIManager.put("Button.margin", new Insets(10, 10, 10, 10) );
JFrame frame = new JFrame("Calculator Panel");
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
frame.add( new CalculatorPanel() );
frame.pack();
frame.setLocationRelativeTo( null );
frame.setVisible(true);
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowUI();
}
});
}
}
You click a button and the value is displayed in a text field.
Do this with the java.awt.Robot class. Do this like so:
//Creating a new robot:
Robot r = new Robot();
//Pressing a key (Put inside click handler method):
r.keyPress(KeyEvent.VK_LEFT /*VK_RIGHT, VK_TOP, and VK_BOTTOM are also acceptable.*/
//Releasing a key (Put inside release handler method):
r.keyRelease(KeyEvent.VK_LEFT /*VK_RIGHT, VK_TOP, and VK_BOTTOM are also acceptable.*/); //Release key
When doing this, you may want to hold the value of the key being pressed. Do this by defining a global variable with the KeyEvent.VK_* value, like so:
//In global space
public static /*Can be private, or protected.*/ int keyPressed = null;
//In click handler body:
keyPressed = KeyEvent.VK_LEFT /*VK_RIGHT, VK_TOP, and VK_BOTTOM are also acceptable.*/; //Set this to the value of the key you are pressing.
//In mouse release handler body:
r.keyRelease(keyPressed);
In the code sample below, if a user changes the contents of the JFormattedTextField then presses Enter, the dialog is supposed to act as if the OK button is pressed. But it takes two presses of Enter for this to happen.
The plain vanilla JTextField always acts as I would expect - changing the text then pressing Enter activates the OK button straight away.
This in on Mac OS X 10.6 with the current Mac Java update 1.6.0_20.
Is this a work-around? Is this a Mac specific problem?
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.text.NumberFormat;
import java.text.ParseException;
public class ScratchSpace {
public static void main(final String[] args) throws ParseException {
final JDialog dialog = new JDialog((Frame) null, "Test", true);
dialog.setLayout(new FlowLayout());
dialog.add(new JLabel("text field: "));
dialog.add(new JTextField(20));
dialog.add(new JLabel("formatted text field: "));
final JFormattedTextField formattedTextField = new JFormattedTextField(NumberFormat.getIntegerInstance());
formattedTextField.setValue(42);
formattedTextField.setColumns(20);
dialog.add(formattedTextField);
final JButton okButton = new JButton(new AbstractAction("OK") {
public void actionPerformed(ActionEvent e) {
dialog.dispose();
}
});
dialog.add(okButton);
dialog.getRootPane().setDefaultButton(okButton);
dialog.pack();
dialog.setLocationRelativeTo(null);
dialog.setVisible(true);
}
}
Adding this code solved the problem,
formattedTextField.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
dialog.dispose();
}
});
This did not solve my problem. However, it seemed that the problem solution was much simpler for me:
private void jTextField1ActionPerformed(java.awt.event.ActionEvent evt) {
add(jTextField1); //this reacts after the "ENTER" gets pressed
jButton1.doClick(); //this activates the button
jTextField1.setText(""); //this removes the text from a text-field
jTextField1.grabFocus(); //this sets a cursor within a text-field
}