I want to make my JFX application simulate arrow key presses (when they are registered in a TextField), but I can't figure out how to send anything other than Strings or bytes.
I'm imagining something like this:
static EventHandler<KeyEvent> KEY() {
E = new EventHandler<KeyEvent>() {
#Override
public void handle(KeyEvent ke) {
if (ke.getCode().equals(KeyCode.UP)) {
try {
//someObject.SimulateKeyPress(KeyCode.UP);
//OR
//coolObject.SendKey((char)KEY_UPKEY));
} catch (Exception ex) {
//Teleport goats
}
}
}
};
return E;
}
Use the class Robot
try {
Robot r = new Robot();
//there are other methods such as positioning mouse and mouseclicks etc.
r.keyPress(java.awt.event.KeyEvent.VK_UP);
r.keyRelease(java.awt.event.KeyEvent.VK_UP);
} catch (AWTException e) {
//Teleport penguins
}
You cannot instantiate the type Robot.
You should rather do :
Robot robot = com.sun.glass.ui.Application.GetApplication().createRobot();
Related
I'm trying to break loop using AWTEventListener, but in 'if' after checking if I pressed ctrl+p it says error by the break;
try {
Robot robot = new Robot();
int z = 0;
while(true) {
robot.mouseMove(x + z, y);
z++;
AWTEventListener listener = new AWTEventListener() {
#Override
public void eventDispatched(AWTEvent event) {
try {
KeyEvent evt = (KeyEvent)event;
if(evt.getID() == KeyEvent.KEY_PRESSED && evt.getModifiers() == KeyEvent.CTRL_MASK && evt.getKeyCode() == KeyEvent.VK_P) {
break; //ERROR
}
}
catch(Exception e) {
e.printStackTrace();
}
}
};
Toolkit.getDefaultToolkit().addAWTEventListener(listener, AWTEvent.KEY_EVENT_MASK);
}
} catch (AWTException e) {
}
I don't think you understand what you're doing when creating the listeners. You're basically creating a class right in place, and that class has a method named eventDispatched(). There's no loop inside eventDispatched(), so there's no loop to break out of.
Furthermore, it's probably a mistake to assume the event is a KeyEvent. That's a side note.
Your listener probably needs to set some field that your while loop is looking at. Instead of while(true) you need to do "while(my listener hasn't set some flag to another value)".
I am learning Java and trying to implement a MouseListener for the first time. I have read the java doc
MouseListener but my code doesnt work, as in nothing happens when i press the button. Here is a jbutton with a pressed and released event. Can someone explain where i have gone wrong?
JButton upButton_1 = new JButton("Up");
upButton_1.addMouseListener(new MouseAdapter(){
public void mousePressed(MouseEvent pevt) {
upButtonPressPerformed(pevt);
}
public void mouseReleased(MouseEvent revt) {
upButtonReleasePerformed(revt);
}
public synchronized void upButtonPressPerformed(
MouseEvent pevt) {
resultsTextArea.setText("Up Button Activated, String: " + downString);
try{
//See Above comments for sending ASCII String
byte[] bytes = DatatypeConverter.parseHexBinary(upString);
TwoWaySerialComm.SerialWriter sw = new TwoWaySerialComm.SerialWriter(
twoWaySerCom.serialPort.getOutputStream());
sw.out.write(bytes);
} catch (IOException e) {
e.printStackTrace();
}
}
public synchronized void upButtonReleasePerformed(
MouseEvent revt) {
resultsTextArea.setText("Up Button released, String: " + downString);
try{
//See Above comments for sending ASCII String
byte[] bytes = DatatypeConverter.parseHexBinary(upString);
TwoWaySerialComm.SerialWriter sw = new TwoWaySerialComm.SerialWriter(
twoWaySerCom.serialPort.getOutputStream());
sw.out.write(bytes);
} catch (IOException e) {
e.printStackTrace();
}
}
});
ActionListener is what you are looking for if you want to work with buttons.
JButton button = new JButton("SomeButton");
button.addActionListener(this);
void ActionPerformed(ActionEvent e) {
if(e.getSource() == button) {
// do whatever you want if button is clicked
}
}
Or you can use anonymous inner class:
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
//do whatever you want
}
});
//or the Java8 version
button.addActionListener((e) -> {
//do whatever you want
});
Whit MouseListener you can listen to events like:
MouseClicked, MouseEntered, MouseExited, MousePresse, MouseReleased.
You could use these, but for button click its more logical to listen to your buttons not your mouse.
I am creating a virtual piano in Java. So far I have action listeners for two of the keys which work for the most part, just not after one another. For example, I hit q on the keyboard and it presses the c key and plays a c, which is what it's supposed to do. But then I want to hit the d key on the piano by hitting w on the keyboard, and it won't do it if I've already hit the q key.
// c key
JButton btnC3 = new JButton("");
btnC3.addKeyListener(new KeyAdapter()
{
#Override
public void keyPressed(KeyEvent e)
{
if (e.getKeyCode() == KeyEvent.VK_Q)
{
btnC3.doClick();
}
}
});
btnC3.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
// play c
try
{
keys.playNote(Notes.c3.getValue());
}
catch (InterruptedException e1)
{
e1.printStackTrace();
}
catch (InvalidMidiDataException e2)
{
e2.printStackTrace();
}
}
});
// d key
JButton btnD3 = new JButton("");
btnD3.addKeyListener(new KeyAdapter() {
#Override
public void keyPressed(KeyEvent e)
{
if (e.getKeyCode() == KeyEvent.VK_W)
{
btnD3.doClick();
}
}
});
btnD3.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
// play d
try
{
keys.playNote(Notes.d3.getValue());
}
catch (InterruptedException e1)
{
e1.printStackTrace();
}
catch (InvalidMidiDataException e2)
{
e2.printStackTrace();
}
}
});
btnD3.setBackground(Color.WHITE);
btnD3.setBounds(wKeyWidth*1, 0, wKeyWidth, wKeyHeight);
frame.getContentPane().add(btnD3);
Focus is the problem. It will work when the q is pressed because that button has the focus. It wont work if w is pressed no matter if you press q first because the "q" button has the focus throughout. You should use KeyBindings instead. They work despite whatever component has focus.
Another solution would be to add the q and w button presses to a keylistener added onto the JFrame and use requestFocus() and grabFocus().
But you would need to add implementation for both the keylistener in the JFrame and the button press and release for the button.
Here is the perfect link to see how focus affects how your key presses work in swing
http://www.javaworld.com/article/2076720/core-java/focus-on-swing.html
The problem is related to key board focus, a KeyListener will only generate events when the component the listener is registered to IS focusable and HAS focus.
Obviously, when a button is "clicked" it gains focus, meaning that none of the other components can responds.
The basic answer is, use is the Use Key Bindings API.
There are a number of choices you can make, you can use the current container to register the key bindings against, for example...
InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
ActionMap am = getActionMap();
JButton btnC3 = new JButton("");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_Q, 0), "c3");
am.put("c3", new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
btnC3.doClick();
}
});
btnC3.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// play c
try {
keys.playNote(Notes.c3.getValue());
} catch (InterruptedException e1) {
e1.printStackTrace();
} catch (InvalidMidiDataException e2) {
e2.printStackTrace();
}
}
});
JButton btnD3 = new JButton("");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_W, 0), "d3");
am.put("d3", new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
btnD3.doClick();
}
});
or you can register them against in the individual components. The choice will mostly come down to how reusable you want the solution to be.
For example, you could create a Action which can be applied to both the JButton and key binding which means you don't need to programmatically click the button.
For example...
public class NoteAction extends AbstractAction {
private Note note;
private Keys keys;
public NoteAction(Note note, Keys keys) {
this.note = note;
this.keys = keys;
}
#Override
public void actionPerformed(ActionEvent e) {
keys.playNote(note.getValue());
}
}
(I don't have your code so I'm just make some of the class names up)
Then you could simply use...
NoteAction noteAction = new NoteAction(Notes.d3, keys);
JButton btnC3 = new JButton(noteAction);
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_Q, 0), "c3");
am.put("c3", noteAction);
to set it up.
See How to Use Actions for more details
The default close shortcut (Cmd+q on Mac) doesn't work on this program i coded in java, do you know why?
I am an absolute beginner and would be glad if you helped me!
The code:
public static void main(String[] args) throws IOException, AWTException{
final Robot robot = new Robot();
robot.delay(2000);
while(true)
{
{
robot.mousePress(InputEvent.BUTTON1_MASK);
robot.mouseRelease(InputEvent.BUTTON1_MASK);
robot.delay(50);
}
}
}
}
That would be because Java is trying to be as cross-platform (or platform-independent) as it can be. You could make your own closing shortcut, using the Key class explained in your previous questions (specifically: How to cast a keyboard event). However, I don't think you could detect mac-specific keys, unless you dive into JNI (Java Native Interface), but if you are a beginner I wouldn't recommend it just yet.
For example, say you would like the shortcut to be CTRL+Q. Add another field in your Key class:
private boolean ctrlPressed = false;
Then, make a pressing check:
#Override
public void keyPressed(KeyEvent e)
{
//Previous code
if(e.getKeyCode() == KeyEvent.VK_CONTROL)
{
ctrlPressed = true;
}
}
#Override
public void keyReleased(KeyEvent e)
{
//Previous code
if(e.getKeyCode() == KeyEvent.VK_CONTROL)
{
ctrlPressed = false;
}
}
And finally, the Q part:
#Override
public void keyTyped(KeyEvent e)
{
if(e.getKeyCode() == KeyEvent.VK_Q && ctrlPressed)
System.exit(0);
}
I make my game run without mouse so using pointer is not a choice. High Score menu will show when player lose.
this is my code
highScore=new MyTextField("Your Name");
highScore.addKeyListener(this);
highScore.setFont(font);
highScore.requestFocusInWindow();
I have tried
highScore.setFocusable(true);
highScore.requestFocusInWindow();
highScore.requestFocus(true);
highScore.requestFocus();
but still not gained focus on my JTextField.
How to focus it?
If you want your JTextField to be focused when your GUI shows up, you can use this:
in = new JTextField(40);
f.addWindowListener( new WindowAdapter() {
public void windowOpened( WindowEvent e ){
in.requestFocus();
}
});
Where f would be your JFrame and in is your JTextField.
if is there only one Top-Level Container then last lines in GUI constructor would be for example
.
.
.
myFrame.setVisible(true);
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
myComponent.grabFocus();
myComponent.requestFocus();//or inWindow
}
});
public void actionPerformed(ActionEvent arg0)
{
if (arg0.getSource()==clearButton)
{
enterText.setText(null);
enterText.grabFocus(); //Places flashing cursor on text box
}
}
Try this one,
myFrame.setVisible(true);
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
myComponent.grabFocus();
myComponent.requestFocus();//or inWindow
}
});
If the page contains multiple item and like to set the tab sequence and focus I will suggest to use FocusTraversalPolicy.
grabFocus() will not work if you are using FocusTraversalPolicy.
Sample code
int focusNumber = 0;
Component[] focusList;
focusList = new Component[] { game, move, amount, saveButton,
printButton, editButton, deleteButton, newButton,
settingsButton };
frame.setFocusTraversalPolicy(new FocusTraversalPolicy() {
#Override
public Component getLastComponent(Container aContainer) {
return focusList[focusList.length - 1];
}
#Override
public Component getFirstComponent(Container aContainer) {
return focusList[0];
}
#Override
public Component getDefaultComponent(Container aContainer) {
return focusList[1];
}
#Override
public Component getComponentAfter(Container focusCycleRoot,
Component aComponent) {
focusNumber = (focusNumber + 1) % focusList.length;
if (focusList[focusNumber].isEnabled() == false) {
getComponentAfter(focusCycleRoot, focusList[focusNumber]);
}
return focusList[focusNumber];
}
#Override
public Component getComponentBefore(Container focusCycleRoot,
Component aComponent) {
focusNumber = (focusList.length + focusNumber - 1)
% focusList.length;
if (focusList[focusNumber].isEnabled() == false) {
getComponentBefore(focusCycleRoot, focusList[focusNumber]);
}
return focusList[focusNumber];
}
});
In my case nothing above worked untill I called requestFocus() AFTER my constructor has returned.
MyPanel panel = new MyPanel(...);
frame.add(panel);
panel.initFocus();
MyPanel.initFocus() would have:
myTextField.requestFocus();
And it works.
This code mouse cursor “jtextfield” “Jcombobox” location focused
try {
Robot robot = new Robot();
int x = Jtextfield.getLocationOnScreen().x;
int y= Jtextfield.getLocationOnScreen().y;
JOptionPane.showMessageDialog(null, x+"x< - y>"+y);// for I location see
robot.mouseMove(x, y);
} catch (AWTException ex) {
ex.printStackTrace();
}
It was not working for me when tried to use:
JOptionPane.showConfirmDialog(...)
But -
I found a solution !
Very primitive, but works.
Just jump to the field by java.awt.Robot using key "Tab".
For example:
Robot robot = new Robot();
robot.keyPress(KeyEvent.VK_TAB);
robot.delay(100);
robot.keyRelease(KeyEvent.VK_TAB);
If you should press multiple times on "Tab" to get your Component you can use below method:
GUIUtils.pressTab(3);
Definition:
public static void pressTab(int amountOfClickes)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
try
{
Robot robot = new Robot();
int i = amountOfClickes;
while (i-- > 0)
{
robot.keyPress(KeyEvent.VK_TAB);
robot.delay(100);
robot.keyRelease(KeyEvent.VK_TAB);
}
}
catch (AWTException e)
{
System.out.println("Failed to use Robot, got exception: " + e.getMessage());
}
}
});
}
If your Component location is dynamic, you can run over the while loop without limitation, but add some focus listener on the component, to stop the loop once arrived to it.
While yourTextField.requestFocus() is A solution, it is not the best since in the official Java documentation this is discourage as the method requestFocus() is platform dependent.
The documentation says:
Note that the use of this method is discouraged because its behavior is platform dependent. Instead we recommend the use of requestFocusInWindow().
Use yourJTextField.requestFocusInWindow() instead.
How about put jTextField.requestFocusInWindow(); into jTextField FocusLost event?
Works for me
have 5 controls on JPanel
Soon as click on MessageBox, focus lost on jTextField.
Used all the suggested codes but no luck
Only above method works my case.