当我创建 Robot 对象时,为什么 JavaFX 会引发 IllegalStateException?

Tii*_*mzy 3 java mouse javafx mouseevent

我正在创建一个应用程序,我想要一个功能,当用户按下 时E,它将把鼠标指针设置到屏幕的中心(使用该moveMouse()方法)。然而,它只是给了我一个IllegalStateException.

我尝试过使用 aGlassRobot代替(来自这个问题并接受了答案),但这只给了我一个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
Run Code Online (Sandbox Code Playgroud)

场景机器人宣言

private static final Robot robot = new Robot() ;
Run Code Online (Sandbox Code Playgroud)

GlassRobot宣言

private static final Robot robot = com.sun.glass.ui.Application.GetApplication().createRobot() ;
Run Code Online (Sandbox Code Playgroud)

当用户按下时将鼠标指针设置为中心的方法E

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() ;

        }
    }
Run Code Online (Sandbox Code Playgroud)
static void setupInventory() {
        robot.mouseMove((double) screenWidth / 2, (double) screenHeight / 2) ;
    }
Run Code Online (Sandbox Code Playgroud)

jew*_*sea 7

您提到的问题已过时(不要使用GlassRobot

该问题提到提出将GlassRobot功能公开 API 的请求。该请求几年前在 JavaFX 11 中完成,公共 API 是Robot(您已经在问题中使用了)。

没有必要使用非公共GlassRobotAPI,并且有很多理由不使用它。

错误消息告诉您问题是什么

This operation is permitted on the event thread only; currentThread = main  
Run Code Online (Sandbox Code Playgroud)

您已robot声明为应用程序类的静态成员。静态成员在类加载时初始化。您的主应用程序类将在主 Java 线程上加载。但是,错误消息指出Robot 必须在 JavaFX 线程上加载。

如何解决您的问题

将您的声明更改为:

private Robot robot;
Run Code Online (Sandbox Code Playgroud)

start()在您的方法(或在 JavaFX 应用程序线程上调用的其他一些方法)中初始化机器人:

@Override
public void start(Stage stage) {
    robot = new Robot();
    // other app logic
}
Run Code Online (Sandbox Code Playgroud)

建议

通常,最好尽量减少 Java 应用程序中的静态和初始化。原因之一是,如果初始化失败并抛出异常,那么该类将无法加载,这可能很难理解(正如您可能已经在这里发现的那样)。避免静态还有其他原因。该建议主要适用于静态。不依赖于静态的静态方法(例如类中的Math静态方法)有时可能没问题。

如果您想了解有关 JavaFX 中线程的更多信息,请阅读应用程序生命周期文档