当前位置: 首页 > 知识库问答 >
问题:

如何在自己的线程中启动JavaFXGUI

阎安邦
2023-03-14

我有一个项目,我需要启动一个GUI,但在另一个不是我的主线程的线程中。

-

-

-

我的意思是,在任何情况下,我都不能在主线程中启动gui。我需要能够与我的控制器通信(示例中没有控制器)。但当我做正常的事情时:。。开始扩展应用程序{..方法,我无法再与控制器通信,因为线程已被占用。下面的代码应该允许我做我需要做的一切,所以我希望有一种方法可以让它工作。

问题是,为什么我的代码不起作用是一个例外:

线程“thread-0”java中出现异常。lang.IllegalStateException:工具箱未初始化

呼叫平台时。runLater()。。在我的吉他课上。

提前谢谢你的帮助。

我的主要班级:

public class Start{
    private void start() {
        GuiThread thread = new GuiThread();
        thread.start();
        System.out.println("here continues the thread, while the GUI is shown");
    }

    public static void main(String[] args) {
        Start main = new Start();
        main.start();
    }
}

我的自定义线程类,我的GUI应该在那里启动:

import javafx.application.Platform;
import javafx.fxml.FXMLLoader;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.stage.Stage;

import java.io.IOException;

public class GuiThread extends Thread {
    @Override
    public void run() {
        super.run();

        // Here i have objects i need to have in the controller

        // Then i have to start my GUI

        // When calling Platform.runLater()... this error shows : Exception in thread "Thread-0" java.lang.IllegalStateException: Toolkit not initialized
        Platform.runLater(() -> {
            Group root;
            try {
                Stage stage = new Stage();
                root = new Group();
                Scene scene = new Scene(root);

                FXMLLoader loader = new FXMLLoader(getClass().getResource("myGui.fxml"));
                Node node = loader.load();

                // Controller stuff

                root.getChildren().add(node);
                stage.setScene(scene);
                stage.show();
            } catch (IOException e) {
                e.printStackTrace();
            }
        });

    }
}

只是一个示例FXML文件:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.StackPane?>


<HBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/10.0.1" xmlns:fx="http://javafx.com/fxml/1">
   <children>
      <StackPane prefHeight="150.0" prefWidth="200.0" HBox.hgrow="ALWAYS">
         <children>
            <Label text="left" />
         </children>
      </StackPane>
      <StackPane prefHeight="150.0" prefWidth="200.0" HBox.hgrow="ALWAYS">
         <children>
            <Label text="right" />
         </children>
      </StackPane>
   </children>
</HBox>

共有1个答案

郭元凯
2023-03-14

通常,您会从应用程序启动任何附加线程。初始化应用程序。启动方法,但在您的情况下,这似乎不是一个选项。

从JavaFX 9开始,您可以在第一次需要访问JavaFX时使用Platform.startup。执行传递给该方法的Runnable后,您应该能够使用Platfrom.run稍后

使用这种方法时,您需要确保在所有其他逻辑完成时关闭,并且不需要显示任何GUI。

Platform.startup(() -> {
    Group root;
    try {
        Stage stage = new Stage();
        root = new Group();
        Scene scene = new Scene(root);

        FXMLLoader loader = new FXMLLoader(getClass().getResource("myGui.fxml"));
        Node node = loader.load();

        // Controller stuff

        root.getChildren().add(node);
        stage.setScene(scene);
        stage.setOnHidden(evt -> Platform.exit()); // make sure to completely shut down JavaFX when closing the window
        stage.show();
    } catch (IOException e) {
        e.printStackTrace();
    }
});
 类似资料:
  • 问题内容: 我正在创建一个Android应用程序,该应用程序必须在后台执行Web请求,然后处理接收到的数据并根据服务器响应修改用户界面。 在后台发布请求和处理数据的目的是避免冻结用户界面。但是目前,我注意到用户界面处于冻结状态,因此我不确定逻辑是否按预期工作。 这是代码的一部分,应该在其自己的线程中发布请求并处理响应,然后将数据传递给GUI: 从实现ServerResponseHandler的主要

  • 问题内容: 我很难找到一种方法来启动,停止和重新启动Java中的线程。 具体来说,我在中有一个类Task(当前实现)。我的主应用程序需要能够在线程上启动此任务,在需要时停止(杀死)该线程,有时还可以杀死并重新启动该线程… 我的第一次尝试是与,但我似乎找不到办法重新启动任务。当我使用任何将来的呼叫失败时,因为是“关机” … 那么,我该怎么做呢? 问题答案: 一旦线程停止,你将无法重新启动它。但是,没

  • 您如何让新启动的活动在Android TalkBack中宣布自己? 我能找到的所有文档都只提到视图,而不是活动,这些视图只有在触摸时才宣布自己。我需要的是,在更改“活动”时,使用一些语音文本来告诉用户他们在应用层次结构中的位置。现在,在每次活动更改时,TalkBack每次都只声明应用程序名称,这没有用。 我尝试过将 contentDescription 添加到活动布局 XML 中的根布局元素,但这

  • 我想这是一个标准的知识问题,但是是否会以线程形式运行? 我想要的是与生产者/消费者的并发会话,这些会话编写/监听他们的特定队列。我已经尝试通过将连接传递给线程来编写一个自定义线程,但是当我创建生产者时,我遇到了一个错误,“我不能在未注册的会话上启动生产者”。

  • 问题内容: 我试图编写一个文件监视器,它将检查文件是否添加了新行,该监视器实际上是一个线程,它将始终由randomaccessfile读取该行。 这是监视器的核心代码: 这是一些帮助类: 这是调用监视器的示例: 现在,我的问题是,如果我仅调用以下代码,代码就可以很好地工作: 这将监视文件的行追加,并通知侦听器。 但是,当我致电: 这意味着我想监视另一个文件而不是之前。 因此,在Monitor中,我

  • 问题内容: 我想运行自己的内部pypi服务器,以便在组织内分发鸡蛋。 我发现了一些项目,例如: http://pypi.python.org/pypi/EggBasket/ http://plone.org/products/plonesoftwarecenter 据我了解,pypi.python.org使用名为Cheese Shop的软件。 我的问题: 为什么我不能使用奶酪店本身?(我找不到它,