Pytanie tak jak w temacie.
W jaki sposób w javafx można nasłuchiwać zdarzenia klawiatury.
Poprzednio w java i java Swing używałem takiej klasy:
package klawiatura;
import com.sun.jna.platform.win32.Kernel32;
import com.sun.jna.platform.win32.User32;
import com.sun.jna.platform.win32.WinDef;
import com.sun.jna.platform.win32.WinUser;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.application.Platform;
public class Klawiatura {
public static void main(String[] args) {
new Keys().start();
}
}
class Keys extends Thread {
private volatile boolean quit;
private WinUser.HHOOK hhk;
private WinUser.LowLevelKeyboardProc keyboardHook;
@Override
public void run() {
final User32 lib = User32.INSTANCE;
WinDef.HMODULE hMod = Kernel32.INSTANCE.GetModuleHandle(null);
keyboardHook = new WinUser.LowLevelKeyboardProc() {
@Override
public WinDef.LRESULT callback(int nCode, WinDef.WPARAM wParam, WinUser.KBDLLHOOKSTRUCT info) {
if (nCode >= 0) {
switch (wParam.intValue()) {
case WinUser.WM_KEYUP:
case WinUser.WM_SYSKEYUP:
// System.out.println("in callback, key=" + info.vkCode);
if (info.vkCode == 27/*Esc+*/) {
quit = true;
} else if (info.vkCode == 65/*[A]*/) {
System.out.println("Nacisnieto Przycisk: [ A ]");
} else if (info.vkCode == 66/*[B]*/) {
System.out.println("Nacisnieto Przycisk: [ B ]");
} else if (info.vkCode == 67/*[C]*/) {
System.out.println("Nacisnieto Przycisk: [ C ]");
} else if (info.vkCode == 112/*[F1]*/) {
System.out.println("Nacisnieto Przycisk: [ F1 ]");
}
}
}
return lib.CallNextHookEx(hhk, nCode, wParam, info.getPointer());
}
};
hhk = lib.SetWindowsHookEx(WinUser.WH_KEYBOARD_LL, keyboardHook, hMod, 0);
System.out.println("Keyboard hook installed, type anywhere, 'q' to quit");
new Thread() {
@Override
public void run() {
while (!quit) {
try {
Thread.sleep(30);
} catch (InterruptedException ex) {
Logger.getLogger(Keys.class.getName()).log(Level.SEVERE, null, ex);
}
}
System.err.println("unhook and exit");
lib.UnhookWindowsHookEx(hhk);
Platform.exit();
System.exit(0);
}
}.start();
// This bit de returns from GetMessage
int result = 0;
WinUser.MSG msg = new WinUser.MSG();
while ((result = lib.GetMessage(msg, null, 0, 0)) != 0) {
if (result == -1) {
System.err.println("error in get message");
break;
} else {
System.err.println("got message");
lib.TranslateMessage(msg);
lib.DispatchMessage(msg);
}
}
lib.UnhookWindowsHookEx(hhk);
}
}
natomiast w JavaFX przy próbie wyświetlenia tekstu w TextArea wywala błąd:
Exception in thread "Thread-3" java.lang.IllegalStateException: Not on FX application thread; currentThread = Thread-3
at com.sun.javafx.tk.Toolkit.checkFxUserThread(Toolkit.java:204)
at com.sun.javafx.tk.quantum.QuantumToolkit.checkFxUserThread(QuantumToolkit.java:364)
at javafx.scene.Scene.addToDirtyList(Scene.java:485)
at javafx.scene.Node.addToSceneDirtyList(Node.java:424)
at javafx.scene.Node.impl_markDirty(Node.java:415)
at javafx.scene.shape.Shape.impl_markDirty(Shape.java:942)
at javafx.scene.Node$6.invalidated(Node.java:1224)
at javafx.beans.property.DoublePropertyBase.markInvalid(DoublePropertyBase.java:112)
at javafx.beans.property.DoublePropertyBase.access$000(DoublePropertyBase.java:52)
at javafx.beans.property.DoublePropertyBase$Listener.invalidated(DoublePropertyBase.java:262)
at com.sun.javafx.binding.ExpressionHelper$SingleInvalidation.fireValueChangedEvent(ExpressionHelper.java:137)
at com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:81)
at javafx.beans.binding.DoubleBinding.invalidate(DoubleBinding.java:222)
at com.sun.javafx.binding.BindingHelperObserver.invalidated(BindingHelperObserver.java:51)
at com.sun.javafx.binding.ExpressionHelper$SingleInvalidation.fireValueChangedEvent(ExpressionHelper.java:137)
at com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:81)
at javafx.beans.binding.BooleanBinding.invalidate(BooleanBinding.java:176)
at com.sun.javafx.binding.BindingHelperObserver.invalidated(BindingHelperObserver.java:51)
at com.sun.javafx.binding.ExpressionHelper$Generic.fireValueChangedEvent(ExpressionHelper.java:349)
at com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:81)
at javafx.beans.property.ReadOnlyIntegerWrapper$ReadOnlyPropertyImpl.fireValueChangedEvent(ReadOnlyIntegerWrapper.java:176)
at javafx.beans.property.ReadOnlyIntegerWrapper.fireValueChangedEvent(ReadOnlyIntegerWrapper.java:142)
at javafx.beans.property.IntegerPropertyBase.markInvalid(IntegerPropertyBase.java:113)
at javafx.beans.property.IntegerPropertyBase.set(IntegerPropertyBase.java:146)
at javafx.scene.control.TextInputControl.selectRange(TextInputControl.java:899)
at javafx.scene.control.TextInputControl.replaceText(TextInputControl.java:470)
at javafx.scene.control.TextInputControl.insertText(TextInputControl.java:397)
at javafx.scene.control.TextInputControl.appendText(TextInputControl.java:387)
at Keyboard.Keys$1.callback(Keys.java:53)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at com.sun.jna.CallbackReference$DefaultCallbackProxy.invokeCallback(CallbackReference.java:293)
at com.sun.jna.CallbackReference$DefaultCallbackProxy.callback(CallbackReference.java:315)
at com.sun.jna.Function.invokeInt(Native Method)
at com.sun.jna.Function.invoke(Function.java:299)
at com.sun.jna.Function.invoke(Function.java:224)
at com.sun.jna.Library$Handler.invoke(Library.java:212)
at com.sun.proxy.$Proxy0.GetMessage(Unknown Source)
at Keyboard.Keys.run(Keys.java:104)
Czy może ktoś mi powiedzieć jak się to robi w javafx?