I am new to Java and am in the process of making a GUI of CLI application of Poker Game. It requires "Enter Key" to continue. I have tried to find out if there is some Event Handler for "Enter Key" so that I could change that Event to Mouse Button. But unfortunately I could not find any such thing. Now I have thought of passing carriage return to Java Console onClick Event. I have tried:
ContinueBtn = new JButton();
ContinueBtn.addMouseListener(this);
.
.
.
public void mouseReleased(MouseEvent e) {
System.out.println("\r\n");
//OR
char c = (char) KeyEvent.VK_ENTER;
System.out.println(c)
//OR
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out));
out.write("\r\n");
out.newLine();
out.flush();
//OR
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out));
out.write((char)10); /*OR*/ out.write((char)13);
}
It is still not working. Can anyone suggest what should I do?
Add proper Action or ActionListener, then implements KeyBindings, output form
KeyBindings should be javax.swing.Action, inside this Action call
myButton.doClick()
that invoke Action or ActionListener added to the JButton
For 'Enter' on JButtons, you probably want to use JRootPane.setDefaultButton(). Both JWindow and JDialog have a getRootPane() method.
The only trick is that the window / dialog has to be visible already to set the default button. I usually just override setVisible() in the windows that need a default button:
public void setVisible(boolean b) {
if (b) {
getRootPane().setDefaultButton(button);
}
super.setVisible(b);
}
I am not clear about your question, but from what i understand about your situation this might help.
(anything like a button)ActionPerformed(java.awt.event.ActionEvent evt)
Key bindings in Swing are handled with InputMaps and ActionMaps.
Sun has a nice tutorial on the key binding API. The tutorial has this to say:
An alternative to key bindings is using key listeners. Key listeners
have their place as a low-level interface to keyboard input, but for
responding to individual keys key bindings are more appropriate and
tend to result in more easily maintained code. Key listeners are also
difficult if the key binding is to be active when the component
doesn't have focus. Some of the advantages of key bindings are they're
somewhat self documenting, take the containment hierarchy into
account, encourage reusable chunks of code (Action objects), and allow
actions to be easily removed, customized, or shared. Also, they make
it easy to change the key to which an action is bound. Another
advantage of Actions is that they have an enabled state which provides
an easy way to disable the action without having to track which
component it is attached to.
java.awt.event.KeyListener (KeyListener Tutorial).
Related
What is the closest equivalent of Java's KeyBindings in C#? I am attempting to port a Swing application to C#, but it is unclear which method I should use.
Here is a sample of the Java I am porting:
Action goUp = new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
panel.upPressed = true;
}
};
Action stopUp = new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
panel.upPressed = false;
}
};
InputMap getInputMap = panel.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
getInputMap.put(KeyStroke.getKeyStroke("W"), "goUp");
getInputMap.put(KeyStroke.getKeyStroke("released W"), "stopUp");
panel.getActionMap().put("goUp", goUp);
panel.getActionMap().put("stopUp", stopUp);
In Winforms, I am not aware of anything that is exactly like InputMap. Keyboard input is usually handled in one of two ways:
Shortcut keys, i.e. MenuItem.Shortcut. This is assignable in the Designer, or in code. Pressing the associated key will invoke the menu item's Click event handler(s). Of course, to use this method requires that the action you want to take is represented in the UI as a menu item.
Various key event handling in the UI. This can get fairly complicated depending on your needs, but is often the most appropriate way, and is the primary way to handle key input not associated with a menu item. The simplest event is the KeyPress event. Given your example, you probably want to handle KeyDown and KeyUp so that you can track the actual state of the key. Note that you will receive multiple KeyDown events as the auto-repeat kicks in for a key; if this would be a problem for your handler, you'll need to track the key state and for a key for which you've already seen KeyDown, only handle the KeyDown event if you've seen the corresponding KeyUp event.
Note that WPF does have a key binding model that is more similar to InputMap. Of course, the syntax is entirely different, but it breaks apart the idea of the menu items, commands, and key bindings, so you can mix and match as necessary (and in particular, have key bindings that don't correspond to any menu item). So if using WPF is an option, you might find that part of the transition easier (and probably only that part, since Swing is otherwise much more like Winforms than WPF :) ).
I am trying to get my application to respond to keyboard input. Eventually, I would like it to register ctrl+f and initiate a search, but I started simple and tried for the space bar. The Java tutorials on using Key Bindings got me this far, but no matter what I apply the key binding to, nothing registers. In the below code, panel is a JPanel and the others are assorted swing objects which have been added to panel.
Action ctrlF = new AbstractAction() {
public void actionPerformed(ActionEvent e) {
System.out.println("Action performed");
}
};
panel.getInputMap().put(KeyStroke.getKeyStroke("SPACE"),"crtlF");
openStallsList.getInputMap().put(KeyStroke.getKeyStroke("SPACE"),"crtlF");
openStalls.getInputMap().put(KeyStroke.getKeyStroke("SPACE"),"crtlF");
stallScroller.getInputMap().put(KeyStroke.getKeyStroke("SPACE"),"crtlF");
assignLabel.getInputMap().put(KeyStroke.getKeyStroke("SPACE"),"crtlF");
tenantInfo.getInputMap().put(KeyStroke.getKeyStroke("SPACE"),"crtlF");
unitSpinner.getInputMap().put(KeyStroke.getKeyStroke("SPACE"),"crtlF");
buildingAddress.getInputMap().put(KeyStroke.getKeyStroke("SPACE"),"crtlF");
buildingLogo.getInputMap().put(KeyStroke.getKeyStroke("SPACE"),"crtlF");
What am I missing here? Does it have something to do with focus? There are a couple of assorted labels and buttons which are not included on that list. Is there any way to get panel to register all of the input from all of it's children?
Thanks
First, you need bind a KeyStroke to some kind of "key". Now personally, it's eaiser to specifiy the virtual key then using a String, as the String value can be a little temperamental, but that's me
panel.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0),"crtlF");
Next, you need to bind the "key" to an Action
panel.getActionMap().put("crtlF", ctrlF);
See How to use key bindings for more details.
The next problem you will have is the component will need to be focused before the key binding can be triggered
You could try and get the InputMap with a different focus requirement using either WHEN_ANCESTOR_OF_FOCUSED_COMPONENT or WHEN_IN_FOCUSED_WINDOW which will allow you to change the focus level required by the component in order for the key binding to be triggered.
i.e.,
int condition = JComponent.WHEN_IN_FOCUSED_WINDOW;
InputMap inputMap = panel.getInputMap(condition);
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0),"crtlF");
//... etc
I have tried multiple times to find out a solution on my own by consulting Google, but this question, as ridiculously easy as it seems, has no documented answer. It seems to me.
All I want to know is: How to call a method from a keystroke?
Example: Pressing ctrl + up -> call method zoomUp();
ps: would be nice if that keystroke could be bound to a JTextPane.
Update
Until now my solution was to:
Create an Item: JMenuItem up = new JMenuItem("up");
Create a shortcut:
up.setAccelerator(KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_UP,
Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
Catch the event by a listener:
up.addActionListener(new java.awt.event.ActionListener() { public
void actionPerformed(ActionEvent event) {
//Do stuff } });
(- never add the Item so it is a hidden shortcut)
But this is obviously ridiculous.
You cannot use JMenuItem to create "hidden" short cuts. The short cuts of JMenuItems become active once the JMenuItem gets indirectly added to a Window (usually via <-JMenu<-JMenuBar<-JFrame). Without that link, it cannot be known whether or not the accelerator is to be triggered or not, as the same accelerator might trigger different actions in different application windows.
You need to use a KeyListener on the component or frame in which you want to react.
So far I've got ESC key to close the window, using the following code:
KeyStroke escapeKeyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0, false);
Action escapeAction = new AbstractAction() {
public void actionPerformed(ActionEvent e) {
screen.dispose();
}
};
screen.getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(escapeKeyStroke, "ESCAPE");
screen.getRootPane().getActionMap().put("ESCAPE", escapeAction);
But I am wondering how I would go about adding a CTRL+A event? I remember reading about a way where you set booleans for keypressed/released, but I don't see that working with this piece of code, so I am wondering how I can implement CTRL+A.
Thank You
It's the second parameter of the KeyStroke.getKeyStroke(...) method that matters, as you'll want to use the InputEvent.CTRL_DOWN_MASK there to let the KeyEvent.VK_A be a control-A.
e.g.,
KeyStroke ctrlAKeyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_A,
InputEvent.CTRL_DOWN_MASK);
I wouldn't worry about using the 3 parameter method that uses a boolean since you're more interested in key press, not key down or key release.
Regarding your comment:
Correction to my earlier comment. It works, if I make it let's say Ctrl+W. Ctrl+A just attempts to do its native "select all" function in a textfield in the frame. Any way to avoid that?
From the little I understand, this will be a problem if the component that has focus (such as a JTextArea) responds directly to the ctrl-A key press. To get around this, you can add the same binding to this component, but being sure to bind it to its InputMap that uses the JComponent.WHEN_FOCUSED; condition.
Bit of a strange one.
I want to have a JTextField, in which the user will type a string. While typing, however, I'd like that text to automatically print to another JTextField in real time.
I'm not sure if this is possible because I can't recall seeing any application do it.
Anyone even seen anything like this before?
Actually, now that I open my eyes a bit, I see that stackoverflow does it.
Are there any known ways of implementing in Java?
You might be able to give the fields the same document instance. For the document you could use one of the classes that swing provides or you could extend your own. The document is the model of the text field.
Alternatively you could use listeners to do the updating. There are many things you can listen and it depends on your needs what suits best. You can listen the document, you can listen keyboard and mouse events, you can listen for action events. (Action events happen in this kind of fields when pressing enter or focus is lost.)
The "same document" approach is the way to go.
Here's some sample code in Groovy (translation to Java is left as an exercise to the reader):
import javax.swing.*
import java.awt.FlowLayout
f = new JFrame("foo")
t1 = new JTextField(10)
t2 = new JTextField(10)
t2.document = t1.document
f.contentPane.layout=new FlowLayout()
f.contentPane.add(t1)
f.contentPane.add(t2)
f.pack()
f.show()
Add an ActionListener, as this will respond for any action changing the text (not just key presses, but also mouse-driven cut-paste). Code not tested...
// changing textField1 updates textField2
textField1.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
textField2.setText(textField1.getText());
}
});
You could add an action listener for the jTextField's key released action.
eg:
jTextField1.addKeyListener(new java.awt.event.KeyAdapter()
{
public void keyReleased(java.awt.event.KeyEvent evt)
{
jTextField1KeyReleased(evt);
}
});
private void jTextField1KeyReleased(java.awt.event.KeyEvent evt)
{
jTextField2.setText(jTextField1.getText());
}
You could use the KeyListener interface, and on each keyTyped event you copy the text to the "duplicate" field.