I'm currently trying to create a little remote-app for Android to control a MediaPlayer (like Rythmbox) on my PC.
Most media-players understand the special keys on my keyboard (like "play/pause" or "next/previous"). My idea is that the Android App sends a command (like "pause") to the PC. On the PC runs a normal Java-Application which receives this commands and simulates a key-press of this special button.
The advantage would be that you can use this App on all platforms for every player which supports this special keys (and they are on almost every new USB-Keyboard).
I searched the JavaDocs for a constant in the KeyEvent-class, but I can't find any. Does anyone know how to simulate a press of one of those buttons and if this is even possible with Java?
Additional library's are okay with me, too, as long as there is no other solution.
Also, I know i should use a Robot to simulate the key-press and this works for all normal keys on my keyboard. I simply can't find any way to simulate a key press on those special keys.
So, I think it's not possible to do this with pure Java. I tried something else to find out which key-code the special keys have, but this small program only returns 0 for those keys (it works for "normal" keys):
public class GetKeycode implements KeyListener{
private JFrame f;
private JLabel feld;
public GetKeycode(){
f = new JFrame("GetKeycode");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.addKeyListener(this);
feld = new JLabel();
f.add(feld);
f.pack();
f.setVisible(true);
}
#Override
public void keyReleased(KeyEvent e) {
feld.setText(e.getKeyCode()+"");
}
public static void main(String[] args) {
new GetKeycode();
}
// Unused:
#Override public void keyPressed(KeyEvent e) {}
#Override public void keyTyped(KeyEvent arg0) {}
}
I hope this will be implemented in future versions of the JRE. But at the moment, there seems to be no solution for this.
Thanks for all the answers anyways.
Have you already tried to send the OS dependent key codes to the Robot? The multimedia keys are unfortunately not directly supported in Java yet, not even in Java 1.7 but most of the keycode definitions in java.awt.event.KeyCode have the same value as their native Windows pendants. The Robot doesn't filter unknown key codes directly in Java but lets its native back end decide what to do with them. So there is a chance that it might work at least on certain platforms.
The MUTE key code would be 0xAD. Here is a list of the Windows Key Codes.
VK_MEDIA_PLAY_PAUSE
VK_VOLUME_MUTE
VK_VOLUME_DOWN
VK_MEDIA_NEXT_TRACK
VK_MEDIA_PREV_TRACK
Control a Windows apps using Java
To temporarily solve your problem just google "rhythmbox android remote." There are some great projects already.
Related
So, I have this method (with nothing in it yet)
class Transmitter {
public static void main(String[] args) {
}
}
and I want to put a keylistener in it, to detect when the space key is pressed.
I've looked at tutorials online, and they are all to complicated for my needs; I just want a simple "Print something in the console" when the space key is pressed. Thanks!
As some others have commented, there is no concept of a key listener from a console application. If you just want to read input keys from the console, you can use System.in.read() within a loop: What is the use of System.in.read()?
Not sure if that's what you are looking for.
I am trying to write a program that uses key events to activate a method. The code works on Windows machines but when transered to Mac it does no respond to my "Spacebar" being pressed. I presume this is to do with the different key codes used.
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_SPACE) {
System.out.println("SPACEBAR");
grid.stepGame();
}
}
Any ideas how i can get this working on Mac?
Edit - The problem has been solved using the answer below - For note though it seems that on Mac the Frame never automatically regains focus, hence why the keylistener doesn't work is another JComponent is activated.
I'm uncertain as to your particular issue but it's a good bet that if you switch to using key bindings instead of key listeners your issue would disapear.
From the Java Tutorials site:
Note:
To define special reactions to particular keys, use key bindings instead of a key listener.
As an example
// Component that you want listening to your key
JComponent component = ...;
component.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0),
"actionMapKey");
component.getActionMap().put("actionMapKey",
someAction);
I am currently developing a media application in java using the gstreamer bindings for java. All is going well except for one small issue regarding the keyboard, specifically the media keys (e.g. play/pause, back, next).
I have Actions that work fine as buttons/menu items for these functions, and was hoping to allow the use of the keys that are on some keyboards (often on laptops). However, I could not find andthing in java.awt.event.KeyEvent to represent these keys. I tried running the snippet of code below, and it worked fine for most keys, including f1-12, but did not respond to 'fn' nor to the media keys while 'fn' was held.
Does anyone know how to get these keys working?
Code:
import javax.swing.*;
import java.awt.event.*;
public class Key extends JFrame{
public Key(){
JTextField f = new JTextField(50);
f.addKeyListener(new KeyAdapter(){
public void keyPressed(KeyEvent e){
System.out.printf("%s : %d \n", e.getKeyChar(), e.getKeyCode());
}
});
setContentPane(f);
pack();
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
setVisible(true);
}
public static void main(String[] args){
new Key();
}
}
If the e.getKeyChar() and e.getKeyCode() keys don't return anything when you press those keys, I'm not aware of any other way to get those events via the standard Java library, other than using JNI to get the codes at a lower level.
You seem to be on the right track, trying to get the key codes when a key is pressed, which is how you would discover key codes when you don't know what the proper constant is in Java.
Other than that, this question seems to offer some possibilities (though I'm not sure if this only works with Microsoft IntelliType devices, or if it will work cross-platform). When I use a Microsoft IntelliType keyboard on my Mac, for example, the media keys seem to work just fine.
I am interacting with a third party application using it's API, and would like to move it to the front of focus (so that it is on top of all other open windows) when a user performs a certain action. While I can move my application up and down in the hierarchy pretty easily, there doesn't appear to be a way to interact with other windows. Is it possible to move another program's window to front with Java?
You can't do it in pure Java code, but you could using JNI. See In Java Swing how do you get a Win32 window handle (hwnd) reference to a window? for how to get a handle to the window. Then you could do something like http://msdn.microsoft.com/en-us/library/ms633545 to move it to the front.
Caveat: This is for windows only
It's not possible in pure Java and on certain OSes it's not even possible to cleanly get the other windows position (for example good luck doing that under OS X 10.4: OS X 10.4 does not have any documented mean to registered for other windows' events... There are "hacks", but they're really hackish, like requiring the user to turn on the "Allow Assistive Device" preferences, which requires the OS X admin passord).
I was looking for a solution to a very similar problem.
Until now I have found one - very fragile! - solution.
It works for my case, because my case involves running entire sessions using java.awt.Robot without user interaction, so it may - or may not - work for your case.
The solution is using java.awt.Robot to send the key strokes like Alt+Tab to bring the desired Window to the front.
This is fragile of course, due to multiple reasons:
The Robot cannot know how often Alt+Tab needs to be send to get the desired window to front. The window is one in many. This solution only works if it's already known which window in terms of Alt-Tab-count it is.
Depending on the OS, the required keystrokes might actually be something else.
In case the OS and the window sequence are known, i.e. the program can know upfront how many Alt-Tab keystrokes would be required, this could sometimes be a solution.
The following Java program demonstrates how to do this. If called without arguments, it generates exactly one Alt+Tab keystroke. If called with arguments, the program assumes the first argument is a number and it will generate as many Alt+Tab keystrokes as specified by that number.
You may want to play around a bit with the timing values given in robot.delay() and robot.setAutoDelay() in order to deliver the best experience on your machine. Hint: at least on Linux, robot.setAutoDelay() should certainly be less than the keyboard repeat delay, otherwise the OS would generate multiple Alt-Tab keystrokes in the system's event queue because of key repetition.
import java.awt.AWTException;
import java.awt.Robot;
import static java.awt.event.KeyEvent.VK_ALT;
import static java.awt.event.KeyEvent.VK_TAB;
import static java.lang.Integer.parseInt;
public class WindowSwitcher {
public static void main(final String... args) throws AWTException {
final int repeat = args.length != 0 ? parseInt(args[0]) : 1;
final Robot robot = createRobot();
robot.keyPress(VK_ALT);
for (int i = 0; i < repeat; i++) {
robot.keyPress(VK_TAB);
robot.keyRelease(VK_TAB);
robot.delay(500);
}
robot.keyRelease(VK_ALT);
}
public static Robot createRobot() throws AWTException {
final Robot robot = new Robot();
robot.setAutoWaitForIdle(true);
robot.setAutoDelay(10);
return robot;
}
}
I have a problem with JTextField.requestFocus() behavior that appears to be different on Mac OS X.
Here is my situation: I have a dialog with a JList and a JTextField. The user is supposed to write a boolean expression in the text field, and the list contains the names of all the variables that might be entered in the expression. Because the user is expected to continue entering the expression after clicking on a variable from the list, the program helpfully calls JTextField.requestFocus(). This way you can e.g click "pvalue" from the list and then type " < 0.05" without the need to click on the textfield in between.
This all works fine on my development machine (Linux), but I got a bug report from a Mac user that clicking on the list actually selects all text in the text field, making it easy to accidentally overwrite what was entered before.
I suspected this is a problem with the Mac look-and-feel, after some searching it seems that indeed there is a "Quaqua.TextComponent.autoSelect" property for the mac look-and-feel that seems to be related to this problem: http://www.randelshofer.ch/quaqua/guide/jtextcomponent.html
My general question is:
Can you suggest a workaround for this problem?
In case that is too broad, an answer to these subquestions would already be a big help:
A possible solution could be to change the property "Quaqua.TextComponent.autoSelect". How do I do that?
I'm not even sure what "Quaqua" is. It looks like it is a customized look and feel. What is the default look and feel for Mac OS X? Does it have a property similar to Quaqua.TextComponent.autoSelect?
Is there a possibility to tweak look and feel for a single component instance only? If so, how?
Is it possible to set the Mac look and feel on my Linux development machine so that I can actually confirm this bug (all the above is really based on hunches and suspicions)? If so, how?
Seems this is a bug of Mac OS. JTextFields select their contents when they gain focus though keyboard tab cycling. If the insertion point is in the middle of the text, the insertion point will remain and the entire text will not be selected.
As a workaround you can override this behavior with the following, it works fine for me:
textfield.setCaret(new DefaultCaret()).
More details you can refer to this and this.
To modify the default behaviour, you can set the system property to false before initializing the UI components: System.setProperty("Quaqua.TextComponent.autoSelect", "false"); To modify a single component, you can use JTextField#putClientProperty("Quaqua.TextComponent.autoSelect", Boolean.FALSE);.
You can find other MacOS L&F specific properties here:
Quaqua Look & Feel - User Guide
A workaround might be (and I haven't tested this) to make the JList that inserts the variable names unfocusable. That way the focus will remain in the text field when you click on an item in the list. I'd recommend to use setRequestEnabled(false) on the JList, so that they are still focusable if you tab to them, but clicking them with the mouse will not focus them.
Sorry to add to an old question, but I just came across this problem and used the following code, which seems a little more complete than the previous example:
// JTextField linkedText
final int
startBefore = linkedText.getSelectionStart(),
endBefore = linkedText.getSelectionEnd();
linkedText.requestFocus(); // this was the original code line!
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
linkedText.setSelectionStart(startBefore);
linkedText.setSelectionEnd(endBefore);
}
});
This appears to protect the current cursor position or selection. (Note: This code must already run in the event dispatch thread, but you need invokeLater anyway or it doesn't work.)
I have an 'is Mac' function, so I did this inside a test for that, but it probably doesn't do any harm to do it on all platforms.
I noticed when looking through the JavaDocs that requestFocus() "is discouraged because its behavior is platform dependent." You should use requestFocusInWindow() instead and see if the same problem occurs with it.
requestFocusInWindow is part of the Focus subsystem, introduced in Java 1.4.
On a side note, the default Apple Look and Feel has at least one property in the apple.laf namespace: apple.laf.useScreenMenuBar
Edit: According to Sun, the Macintosh look and feel is only available on Macs.
While using requestFocusInWindow() is indeed encouraged over requestFocus(), it still produces the same problematic behavior on Macs (e.g., highlighting of full text field).
One workaround I got to work was to explicitly set the cursor position after requesting focus:
JTextField.requestFocusInWindow();
JTextField.setCaretPosition(JTextField.getDocument().getLength() - 1);
Note the "-1" is necessary, otherwise it will continue to highlight the entire field.
I'm curious to know if this solution is platform independent. Does this screw up the desired Linux or Windows behavior?
Mac will select the contents of the text field when the field gains focus. You can restore the state of the text field if you listen for the focus change event.
// JTextField linkedText
// Cache the state of the JTextField prior to requesting focus
final int
startBefore = linkedText.getSelectionStart(),
endBefore = linkedText.getSelectionEnd();
linkedText.requestFocus(); // this was the original code line!
// Use a focus listener to listen for the focus change and then
// reset the selected text to protect the cursor position
linkedText.addFocusListener ( new FocusListener()
{
public void focusGained( FocusEvent event ) {
linkedText.setSelectionStart( startBefore );
linkedText.setSelectionEnd( endBefore );
}
public void focusLost( FocusEvent event ) {
// do nothing
}
} );
Thank you for sharing your ideas. I had the same problem on my java application where on my windows system there wasn't a problem, but on my Mac OS X Yosemite I couldn't change the input. The focus wouldn't stay on the JTextField. Thanks to this thread I was able to fix my problem.
If you change the look and feel of the buttons and input boxes you maintain the focus and you can type again. The reset of the frame stays in the standard Mac OS look.
This is my code that I use in my java main methode. If you want to fix the problem past the try-catch code in your main methode.
public class Venster extends JFrame {
public static void main(String[] args) {
//Change L&F for mac
//Mac JTextField Bug Fix
try {
// Set cross-platform Java L&F (also called "Metal")
UIManager.setLookAndFeel(
UIManager.getCrossPlatformLookAndFeelClassName());
} catch (UnsupportedLookAndFeelException e) {
System.out.println("L&F not supported" + e.getMessage());
} catch (ClassNotFoundException e) {
System.out.println("Fout: " + e.getMessage());
} catch (InstantiationException e) {
System.out.println("Fout: " + e.getMessage());
} catch (IllegalAccessException e) {
System.out.println("Fout: " + e.getMessage());
}
//The app
JFrame frame = new JFrame();
frame.setSize(1000, 520);
frame.setResizable(false);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setTitle("10 More Bullets by Frank Peters");
frame.setContentPane(new SpeelVeld());
frame.setVisible(true);
frame.setLocationRelativeTo(null); //start app in center
}
}
Soure:
http://docs.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html