加载 fxml 作为后台进程 - Javafx

2024-01-06

我最初的 fxml(比如说home.fxml)有很多功能,因此需要很多时间才能完全加载。因此,为了避免程序启动和 fxml 加载之间的时间间隔,我又引入了一个 fxml(例如loader.fxml)带有 gif 图像,该图像应在加载主 fxml 时出现。 问题是我的 loader.fxml 中的 gif 图像没有移动,因为程序挂起,直到 home.fxml 完全加载。 为了避免这种情况,我将 home.fxml 加载移动到线程中,如下面的代码所示。

public class UATReportGeneration extends Application {

    private static Stage mainStage;

    @Override
    public void start(Stage stage) {
        Parent loaderRoot = null;
        try {
            loaderRoot = FXMLLoader.load(getClass().getResource("/uatreportgeneration/fxml/Loader.fxml"));
        } catch (IOException ex) {
            Logger.getLogger(UATReportGeneration.class.getName()).log(Level.SEVERE, null, ex);
        }
        Scene loadScene = new Scene(loaderRoot);
        stage.setScene(loadScene);
        stage.initStyle(StageStyle.UNDECORATED);
        stage.getIcons().add(new Image(this.getClass().getResourceAsStream("/uatreportgeneration/Images/logo.png")));

        stage.show();


        mainStage = new Stage(StageStyle.UNDECORATED);
        mainStage.setTitle("Upgrade Analysis");
        mainStage.getIcons().add(new Image(this.getClass().getResourceAsStream("/uatreportgeneration/Images/logo.png")));
        setStage(mainStage);

        new Thread(() -> {
            Platform.runLater(() -> {
                try {
                    FXMLLoader loader = new FXMLLoader();
                    Parent root = loader.load(getClass().getResource("/uatreportgeneration/fxml/Home.fxml"));

                    Scene scene = new Scene(root);
                    mainStage.setScene(scene);
                    mainStage.show();
                    stage.hide();
                    System.out.println("Stage showing");
                    // Get current screen of the stage
                    ObservableList<Screen> screens = Screen.getScreensForRectangle(new Rectangle2D(mainStage.getX(), mainStage.getY(), mainStage.getWidth(), mainStage.getHeight()));
                    // Change stage properties
                    Rectangle2D bounds = screens.get(0).getVisualBounds();
                    mainStage.setX(bounds.getMinX());
                    mainStage.setY(bounds.getMinY());
                    mainStage.setWidth(bounds.getWidth());
                    mainStage.setHeight(bounds.getHeight());
                    System.out.println("thread complete");
                } catch (IOException ex) {
                    Logger.getLogger(UATReportGeneration.class.getName()).log(Level.SEVERE, null, ex);
                }

            });
        }).start();

    }

    public static Stage getStage() {
        return mainStage;
    }

    public static void setStage(Stage stage) {
        mainStage = stage;
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {

        launch(args);
    }

}

但在这段代码之后,我的程序也挂起了(gif 图像没有移动)。如果我在外部加载 fxmlPlatform.runLater(),我得到了例外Not on FX Thread.

我也厌倦了使用Task()但从那以后,gif 图像正在移动,但如果我尝试在外部加载 fxml,则 fxml 不会在后台加载Platform.runLater().

任何人都可以帮助我并告诉我如何更正代码,以便我的 fxml 在后台加载而不干扰前台进程。


Use a Task。您需要安排在 FX 应用程序线程上创建场景并更新舞台。最干净的方法是使用Task<Parent>:

Task<Parent> loadTask = new Task<Parent>() {
    @Override
    public Parent call() throws IOException {
        FXMLLoader loader = new FXMLLoader();
        Parent root = loader.load(getClass().getResource("/uatreportgeneration/fxml/Home.fxml"));
        return root ;
    }
};

loadTask.setOnSucceeded(e -> {
    Scene scene = new Scene(loadTask.getValue());

    mainStage.setScene(scene);
    mainStage.show();
    stage.hide();
    System.out.println("Stage showing");
    // Get current screen of the stage
    ObservableList<Screen> screens = Screen.getScreensForRectangle(new Rectangle2D(mainStage.getX(), mainStage.getY(), mainStage.getWidth(), mainStage.getHeight()));
    // Change stage properties
    Rectangle2D bounds = screens.get(0).getVisualBounds();
    mainStage.setX(bounds.getMinX());
    mainStage.setY(bounds.getMinY());
    mainStage.setWidth(bounds.getWidth());
    mainStage.setHeight(bounds.getHeight());
    System.out.println("thread complete");
});

loadTask.setOnFailed(e -> loadTask.getException().printStackTrace());

Thread thread = new Thread(loadTask);
thread.start();

这是使用此技术的 SSCCE:

main.fxml:

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

<?import javafx.scene.layout.VBox?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.TextField?>

<VBox spacing="10" xmlns:fx="http://javafx.com/fxml/1" fx:controller="MainController">
    <padding>
        <Insets top="24" left="24" right="24" bottom="24"/>
    </padding>
    <TextField />
    <Button fx:id="button" text="Show Window" onAction="#showWindow"/>
</VBox>

主控制器(使用Task方法如上所示):

import java.io.IOException;

import javafx.concurrent.Task;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.stage.Stage;

public class MainController {
    @FXML
    private Button button ;
    @FXML
    private void showWindow() {
        Task<Parent> loadTask = new Task<Parent>() {
            @Override
            public Parent call() throws IOException, InterruptedException {

                // simulate long-loading process:
                Thread.sleep(5000);

                FXMLLoader loader = new FXMLLoader(getClass().getResource("test.fxml"));
                Parent root = loader.load();
                return root ;
            }
        };

        loadTask.setOnSucceeded(e -> {
            Scene scene = new Scene(loadTask.getValue());
            Stage stage = new Stage();
            stage.initOwner(button.getScene().getWindow());
            stage.setScene(scene);
            stage.show();
        });

        loadTask.setOnFailed(e -> loadTask.getException().printStackTrace());

        Thread thread = new Thread(loadTask);
        thread.start();
    }
}

测试.fxml:

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

<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.Button?>
<?import javafx.geometry.Insets?>

<BorderPane xmlns:fx="http://javafx.com/fxml/1" fx:controller="TestController">
    <padding>
        <Insets top="24" left="24" right="24" bottom="24"/>
    </padding>
    <center>
        <Label fx:id="label" text="This is a new window"/>
    </center>
    <bottom>
        <Button text="OK" onAction="#closeWindow" BorderPane.alignment="CENTER">
            <BorderPane.margin>
                <Insets top="5" bottom="5" left="5" right="5"/>
            </BorderPane.margin>
        </Button>
    </bottom>
</BorderPane>

测试控制器:

import javafx.fxml.FXML;
import javafx.scene.control.Label;

public class TestController {
    @FXML
    private Label label ;
    @FXML
    private void closeWindow() {
        label.getScene().getWindow().hide();
    }
}

主要应用:

import java.io.IOException;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class Main extends Application {

    @Override
    public void start(Stage primaryStage) throws IOException {
        primaryStage.setScene(new Scene(FXMLLoader.load(getClass().getResource("main.fxml"))));
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}

请注意,按下按钮后,您仍然可以在“加载”FXML 的五秒钟内在文本字段中键入内容,因此 UI 仍保持响应状态。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

加载 fxml 作为后台进程 - Javafx 的相关文章

随机推荐

  • AngularJS:ng-bind-html 不适用于按钮标签

    我在 div ng bind html 中动态打印输入类型按钮时遇到问题 HTML 模板
  • 为什么当我更新实体框架模型时 Visual Studio 会删除我的类

    当我更新 EF 模型 版本 5 时 我遇到了一个奇怪的问题 它删除属于该模型的所有类 我的情况是这样的 我更改了两个表的键列 这两个表引用了我的主表 更新模型并未对 edmx 进行这些更改 因此我删除了这三个表 主表和两个查找表 保存了 e
  • Firebase android 无法在测试设备之外工作

    我有这个新应用程序 并添加了 Firebase Firestore 和 Cloud Firestore 用户可以使用邮箱和密码进行注册 并登录成功 然后用户可以在我的个人资料中输入生日并更新信息 问题是这样的 在模拟器中工作正常 在测试设备
  • Oracle:年份必须介于 -4713 和 +9999 之间,并且不能为 0

    我有一个像这样的 Oracle 表 EMPNO HIREDATE INDEX NUM 1 2012 11 13 1 2 2 1 3 2012 11 17 1 4 2012 11 21 1 5 2012 11 24 1 6 2013 11 2
  • Symfony 2.4 从控制器执行命令

    我想从我的控制器执行命令 fos elastica populate 我尝试了该代码 但它不起作用 我得到错误 1 var dump 显示 command fos elastica populate app new Application
  • 将 ASP.NET 菜单控件绑定到 XML

    我正在尝试将我自己的 xml 文件 出于某些特定目的 我不想使用站点地图 绑定到 ASP NET 控件 我有这段代码 在我找到的一些文章的帮助下 应该将 ASP NET 菜单控件绑定到 xml 文件 但事实并非如此 我错过了什么吗 XmlD
  • 调试器(或日志)中类似 NSDictionary 的漂亮打印

    这已经困扰我一段时间了 如何抵消在调试器中转储对象时发生的丑陋转义po foo 或通过NSLog 我尝试了多种方法来实施 description or debugDescription无济于事 鉴于这个简单的类 interface Foo
  • 在 Python 脚本中使用 Scrapy Spider 输出时出现问题

    我想在 python 脚本中使用蜘蛛的输出 为了实现这一点 我根据另一个代码编写了以下代码thread https stackoverflow com questions 40237952 get scrapy crawler output
  • 数据帧列中动态长度的 Pyspark 字符串数组进行 onehot 编码

    我想转换包含以下字符串的列 ABC def ghi Jkl ABC def Xyz ABC 进入这样的编码列 1 1 1 0 0 1 1 0 1 0 0 1 0 0 1 pyspark ml feature 中有一个类吗 编辑 在编码列中
  • 使用 AChartEngine 库的条形图

    我有一个条形图使用AChartEngine库如下图 public class MainActivity extends Activity private String mMonth new String Jan Feb Mar Apr Ma
  • Youtube API,gapi没有定义?

    我正在尝试做一个 Youtube API 我觉得除了这个gapi和res之外我一切都正常 它说gapi未定义 我怎样才能做到这一点 function tplawesome e t res e for var n 0 n
  • 从具有“路径中的非法字符”的位置执行 CMD.EXE 中的 Powershell 脚本

    我试图在 cmd exe 中调用 Powershell 脚本 该脚本位于如下位置 c Data foo bar location 1 ShellScript ps1 当我调用这个脚本时 我尝试在路径周围使用单引号和双引号 但没有成功 Pow
  • 从时间轴中提取 Google 位置历史记录

    请注意 由于 Google 的 时间轴 发生了变化之前的答案不再有效 https stackoverflow com questions 18290525 wget your google location history daily 谷歌
  • ROS 从 python 节点发布数组

    我是 ros python 的新手 我正在尝试从 python ros 节点发布一个一维数组 我使用 Int32MultiArray 但我无法理解多数组中布局的概念 谁能给我解释一下吗 或者还有其他方式发布数组吗 Thanks usr bi
  • 如何在 Kotlin 中使用 ViewModel 测试协程?

    我无法测试我的方法 感觉它没有到达 uiScope launch 块内部 并且我已经发布了我正在尝试测试的 viewModel 方法 并且fetchActivationCodeWithDuration是挂起功能 底部是我的测试类 我收到这条
  • Unix 系统中的文件 read() 函数

    下面的代码重新启动read 如果由于信号中断而导致功能失败 这read 从中断处继续读取 因此 如果read 在阅读之前被中断EOF字符 它会返回什么 读取了多少字节 int r read int fd void buf int size
  • 在范围内分组选择

    From Table A B 1 A 3 B 6 C 7 C 8 X 9 Y 15 Z 16 R 17 t 23 T 43 e 如何带来这个结果 Range A Count B 1 10 6 11 20 3 21 30 1 31 40 1
  • 不允许用户停止 javascriptalert()

    我正在开发 MVC 4 Web 应用程序 我使用 javascript 和 jquery 来做很多事情 但对于这样的信息 我使用alert 函数向用户显示各种消息 问题是 用户可以阻止此警报的出现 如果用户这样做 很多重要的消息和信息将不会
  • 在 WinForms 应用程序中编译 ASPX

    我正在编写一个发送电子邮件消息 如邮件合并 的 WinForms 应用程序 我想使用 ASP Net 的渲染引擎来渲染消息的 HTML 正文 在没有整个 ASP Net 运行时的情况下获取单个 ASPX 页面的渲染输出的最简单方法是什么 为
  • 加载 fxml 作为后台进程 - Javafx

    我最初的 fxml 比如说home fxml 有很多功能 因此需要很多时间才能完全加载 因此 为了避免程序启动和 fxml 加载之间的时间间隔 我又引入了一个 fxml 例如loader fxml 带有 gif 图像 该图像应在加载主 fx