I've written a basic calculator type program using WindowsBuilder in Eclise neon and Java 1.8. It's pretty much complete, with everything working how I want it to. Except keyboard entry.
As a finishing touch I'd like to detect keyTyped events and map them to button presses so users can use the keyboard for entry instead of clicking buttons with the mouse.
I've added 'implements KeyListener' to the program class...
public class CashRegister implements KeyListener {
private JTextField keyb;
I've tried to set a listener to a invisible JTextField called keyb....
private void initialize() {
keyb = new JTextField(20);
keyb.addKeyListener(this);
keyb.setFocusable(true);
keyb.requestFocusInWindow();
And I've added methods to handle the captured keypress...
public void keyTyped (KeyEvent e) {
String out = "";
out = out + e.getKeyChar();
pence1text.setText(out);
}
public void keyPressed (KeyEvent e) {
}
public void keyReleased (KeyEvent e) {
}
So, at this stage all I'm expecting, prove it is working, is the keycharacter I press to appear in the textfield called 'pence1text'. However, it doesn't work, when I press the a key nothing is displayed.
I think it could be a focus problem. Googling around and checking stackoverlow lead me to add the following lines...
keyb.setFocusable(true);
keyb.requestFocusInWindow();
as above, but still no luck.
Does anyone have any ideas what I am doing wrong, or what I can try next?
Thanks
Thanks to user Andrew Thompson for pointing me back to the docs and a re-read.
The problem is that the JTextField is not visable and thus can't be given focus. If I add the listener to a textfield that is visable then the program works correctly. However if the user uses the mouse to click a button it loses focus and breaks the implementation...so I need to rethink the code and keep looking at focuse settings.
As a finishing touch I'd like to detect keyTyped events and map them to button presses so users can use the keyboard for entry instead of clicking buttons with the mouse.
Don't use a KeyListener.
Instead you should be using Key Bindings. Read the section from the Swing tutorial on How to Use Key Bindings for basic information.
Also check out: how to put actionlistenerand actioncommand to multiple jbuttons for a working example that shows how you can apply the key bindings to a calculator.
Related
So I am building an login frame using Netbeans 8.1. The problem is that after the user has typed in their username, I want them to be able to press the tab key and then have the password textField selected, but instead of this, the 'Login' button is selected.
On startup the username field is selected.
Then when I press tab it looks like this
But instead I want it to look like this when I press tab
Any help is welcome, but I would prefer it if I can do this without getting into the code and can use the Netbeans GUI instead(the project is only about designing the GUI, and nothing about the actual code).
You need order your component indexes, it calls tab index.
NetBeans 8.0 I believe the first component (ie. textBox) you add to the design window should be the one the cursor defaults to when you run the program. You can set the order for tabbing from component to component when you run the program in the design window. Select the first component. In the Properties window, go to nextFocusableComponent and choose the next component you want to tab to in the dropdown list. Repeat for rest of components
I hope this helps you!
Look at this answer.
You can implement your own FocusTraversalPolicy which will manage the tab order. You can then assign it to your frame with the setFocusTraversalPolicy method.
You can find some more explanations in Oracle's doc.
No Tab key-pressed or key-released events are received by the key event listener. This is because the focus subsystem consumes focus traversal keys, such as Tab and Shift Tab.
See: http://docs.oracle.com/javase/tutorial/uiswing/events/keylistener.html
To solve this, apply the following to the component that is firing the key events (e.g., the TextArea):
.setFocusTraversalKeysEnabled(false)
Using this method, you must then handle focus traversal explicitly. Alternatively, the KeyEventDispatcher class can be used to pre-listen to all key events.
you can do following way also
txtUserName.addKeyListener(new KeyAdapter()
{
public void keyReleased(KeyEvent arg)
{
if (arg.getKeyCode() == KeyEvent.VK_ENTER)
{
txtPassword.requestFocus();
}
}
});
txtPassword.addKeyListener(new KeyAdapter()
{
public void keyReleased(KeyEvent arg)
{
if (arg.getKeyCode() == KeyEvent.VK_ENTER)
{
btnLogin.doClick();
}
}
});
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.
I know the title didnt say much, but here I go with a clearer explanation:
I have made a tool/app in netbeans that extends JFrame. It has a button and i've added a keyListener when the button is pressed. It gets if the VK_DOWN button is pressed, if yes, it presses it 4 times and then presses enter. this works very fine, but I want to use this in a game. But when I have the app running, if i click on something else, it takes away the priority (i hope thats the right word here..), it doesnt work anymore unless I click on the app and make it top priority again..
Here is the code for the button:
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
jButton1.addKeyListener(new KeyAdapter() {
public void keyReleased(KeyEvent e) {
}
public void keyTyped(KeyEvent e) {
// TODO: Do something for the keyTyped event
}
public void keyPressed(KeyEvent e) {
// TODO: Do something for the keyPressed event
if (e.getKeyCode() == e.VK_L){
System.out.println("Works");
}
if (e.getKeyCode() == e.VK_DOWN){
System.out.println("Down Arrow Pressed!");
e.setKeyCode(e.VK_DOWN);
e.setKeyCode(e.VK_DOWN);
e.setKeyCode(e.VK_DOWN);
e.setKeyCode(e.VK_DOWN);
e.setKeyCode(e.VK_ENTER);
}
}
});
}
I want to press the VK_DOWN arrow key in the game and let the app press it 4 times and then press enter by itself. This works only when I'm running the app on top of everything else; but if Im running the game, the game takes the higher priority and so the app dont work ..
Please help.
Check out this API:
"JNativeHook is a library to provide global keyboard and mouse hooking for Java. The primary purpose is to provide a portable and reliable method for delivering keyboard and mouse events to a Java application that would otherwise be inaccessible. This is beneficial for applcatiions that run in the background but may require user interaction though hotkeys or mouse events."
http://code.google.com/p/jnativehook/
You cannot do what you are looking to do with Java unless you use some native code.
Uh, not sure whether it will work, but try the Robot class from awt package to generate your Key-Events. It shall work better than your code.
I have a keylistener attached to my frame in java, i can detect key presses when I hit any key, a strange thing is happening however. My game is a minesweeper game, I have a restart button that basically clears the board and remines it. The weird thing is when I click the button with the mouse everything clears fine and the board is remined but the keylistener stops working. Even stranger I have a jmenuitem that basically does a automated click of the button. So its like restartbutton.doclick()
if i click the jmenuitem to restart it restarts fine clears everything and the keylistener still functions. I can even see the button being clicked. Any ideas why this could be happening?
Thanks
this is attached to my main frame. this is the listener that stops working after clicking the button.
frame.addKeyListener(new KeyListener(){
public void keyReleased(KeyEvent e){
}
public void keyPressed(KeyEvent e){
System.out.println("hey");
int keycode = e.getKeyCode();
if(e.isControlDown() & keycode==KeyEvent.VK_C){
balh blah balh
}
}
public void keyTyped(KeyEvent e){
}
});
Suggestions:
Yours is a focus issue, where the KeyListener stops working because the container it is listening to has lost focus to the JButton.
One solution is to make the JButton not able to gain focus by calling setFocusable(false) on it.
But I recommend that you don't use a KeyListener at all if possible, but rather key bindings, since with bindings you don't have this issue and also it is a higher level construct.
Edit
Regarding:
what would be the best way to change that to a key binding?
Best would be to go through the Key Bindings tutorial and to implement the recommendations found there.
this is focus problem, you can use this code to give focus again
getTopLevelAncestor().requestFocus();
Based on the answer to this similar question, I implemented the KeyEventDispatcher rather than using the default listeners. I believe this function will be fairly global though, so you might need to check and make sure the right things are visible/focused.
KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher( new KeyEventDispatcher() {
public boolean dispatchKeyEvent(KeyEvent e) {
if (e.getID() == KeyEvent.KEY_PRESSED) {
System.out.println("tester");
}
return false;
}
I was able to solve this problem by setting the setFocused property of the container to be true:
frame.setFocusable(true);
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.