我正在创建一个应用程序,我想要一个功能,当用户按下 E 时,它将把鼠标指针设置到屏幕中心(使用
moveMouse()
方法)。然而,它只是给了我一个IllegalStateException
。
我尝试使用
GlassRobot
代替(来自 this 问题并接受了答案),但这只给了我一个 IllegalAccessException
。我究竟做错了什么?我需要添加一些东西吗?
IllegalStateException
注意:底部附近有评论
Exception in thread "main" java.lang.reflect.InvocationTargetException
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at java.base/sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:1082)
Caused by: java.lang.ExceptionInInitializerError
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:465)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:364)
... 5 more
Caused by: java.lang.IllegalStateException: This operation is permitted on the event thread only; currentThread = main
at javafx.graphics/com.sun.glass.ui.Application.checkEventThread(Application.java:447)
at javafx.graphics/javafx.scene.robot.Robot.<init>(Robot.java:70)
at com.galactify.tiles/com.galactify.tiles.HelloApplication.<clinit>(HelloApplication.java:37) // This is where the Robot object is created
... 11 more
private static final Robot robot = new Robot() ;
private static final Robot = Robot robot = com.sun.glass.ui.Application.GetApplication().createRobot() ;
static void onKeyReleased(KeyEvent evt) {
KeyCode key = evt.getCode() ;
out.println(key + " is released") ;
switch (key) {
case F11 -> {
stage.setFullScreen(!isFullscreen) ;
isFullscreen = !isFullscreen ;
}
case C -> {
stage.close() ;
isClosed = true ;
}
case E -> setupInventory() ;
}
}
static void setupInventory() {
robot.mouseMove((double) screenWidth / 2, (double) screenHeight / 2) ;
}
GlassRobot
)问题提到提出将
GlassRobot
功能公开 API 的请求。该请求几年前在 JavaFX 11 中完成,公共 API 是 Robot
(您已经在问题中使用了)。
没有必要使用非公开的
GlassRobot
API,并且有很多理由不使用它。
This operation is permitted on the event thread only; currentThread = main
您已将
robot
声明为应用程序类的静态成员。静态成员在类加载时初始化。您的主应用程序类将在主 Java 线程上加载。但是,错误消息指出 Robot
must 必须加载到 JavaFX 线程上。
将您的声明更改为:
private Robot robot;
在您的
start()
方法(或在 JavaFX 应用程序线程上调用的其他方法)中初始化机器人:
@Override
public void start(Stage stage) {
robot = new Robot();
// other app logic
}
通常最好尽量减少 Java 应用程序中的静态和初始化。原因之一是,如果初始化失败并抛出异常,那么该类将无法加载,这可能很难理解(正如您可能已经在这里发现的那样)。避免静态还有其他原因。请注意,此建议主要适用于静态。不依赖于静态的静态方法,例如
Math
类中的方法,有时可能没问题。
如果您想了解有关 JavaFX 中线程的更多信息,请阅读 应用程序生命周期文档。