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

问题描述 投票:0回答:1

我正在创建一个应用程序,我想要一个功能,当用户按下 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() ;

当用户按下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() ;

        }
    }
static void setupInventory() {
        robot.mouseMove((double) screenWidth / 2, (double) screenHeight / 2) ;
    }
java javafx mouseevent mouse
1个回答
1
投票

您提到的问题已过时(不要使用
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 中线程的更多信息,请阅读 应用程序生命周期文档

© www.soinside.com 2019 - 2024. All rights reserved.