gpt4 book ai didi

java - PreLoader 的多线程 - JavaFX

转载 作者:行者123 更新时间:2023-11-30 01:41:10 26 4
gpt4 key购买 nike

我正在开发一个 JavaFX 应用程序,该应用程序需要在启动主应用程序阶段之前从文件中加载资源。我完成此任务的解决方案是使用 PreLoader,以便用户在加载资源之前无法与应用程序交互(非常标准的东西)。

我有一个扩展 PreLoader 类的类,该类创建一个加载 .fxml 文件的对象,该文件是 PreLoader 场景将显示的内容。它工作得很好,直到我尝试插入代码来加载文件。

我想同时执行此操作,以便在加载文件期间状态会更新到屏幕上。我已经研究过使用此处的任务和论坛,但没有任何帮助,因为我不知道将代码放在哪里。

扩展预加载器的类:

public class SplashPreLoader extends Preloader {
private Stage stage;
private SplashScene loadScreen;

public void start(Stage stage) throws Exception {
SplashScene intro = new SplashScene();
this.loadScreen = intro;
this.stage = stage;
stage.setScene(new Scene(intro, 475, 425));
stage.initStyle(StageStyle.UNDECORATED);
stage.show();
}

@Override
public void handleProgressNotification(ProgressNotification pn) {
//bar.setProgress(pn.getProgress());
}

@Override
public void handleStateChangeNotification(StateChangeNotification evt) {
if (evt.getType() == StateChangeNotification.Type.BEFORE_LOAD) {
//loadScreen.setStatusMessage("Hello Mister");
}
if (evt.getType() == StateChangeNotification.Type.BEFORE_START) {
/* Task<Void> task = new Task<Void>() {
@Override
public Void call() {
updateMessage("this mesashlkjfhkjlsd");
return null ;
}
};
statusMessage.textProperty().bind(task.messageProperty());
task.messageProperty().addListener((obs, oldMessage, newMessage) -> loadScreen.setStatusMessage(newMessage));
Thread th = new Thread(task);
th.setDaemon(true);
th.start();*/

//loadScreen.loadWebDriver();

stage.hide();
}
}

场景组件:

public class SplashScene extends StackPane {

@FXML public Label statusMessage;

public SplashScene() {
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("splash_scene.fxml"));
fxmlLoader.setRoot(this);
fxmlLoader.setController(this);

//statusMessage.setTextFill(Color.WHITE);

try {
fxmlLoader.load();
} catch (IOException exception) {
throw new RuntimeException(exception);
}

}

public String getStatusMessage() { return statusMessageProperty().getValue(); }

public void setStatusMessage(String value) {
statusMessageProperty().set(value);
System.out.println("at hert");
}

public StringProperty statusMessageProperty() { return statusMessage.textProperty(); }

public void loadWebDriver() {
//This is the function that I want to call to load all the files.
}

statusMessage 是我要在加载文件时修改的标签。我尝试将任务(线程)放在 loadWebDriver() 函数中、start() 末尾以及前面的 if 子句中,但它没有产生我想要的结果。

我也觉得很奇怪,因为当我在没有 task 的情况下尝试此操作时,我在文件加载代码之前有标签更改代码,但它们总是以相反的顺序执行。

我觉得这可以从文档中得到帮助,但对我来说没有任何意义..有人知道这意味着什么吗?

请注意,预加载器与其他 JavaFX 应用程序(包括 FX 线程)遵循相同的规则规则。特别是,类构造函数和 init() 方法将在非 FX 线程上调用,并且 start() 将在 FX 应用程序线程上执行。这也意味着应用程序构造函数/init() 将与预加载器 start() 同时运行。

我需要使用 init() 方法吗?

最佳答案

这是一个示例,希望对您有所帮助。您可以做的一件事是使用 Task 加载所有数据。当Task完成后,使用 Applying MVC with JavaFX 中的想法将Model传递给任何需要它的Controller

主要

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

import java.io.IOException;
import javafx.concurrent.Task;

/**
* JavaFX App
*/
public class App extends Application {



@Override
public void start(Stage primaryStage) throws IOException {
FXMLLoader loader = new FXMLLoader(getClass().getResource("primary.fxml"));
Parent root = loader.load();
PrimaryController primaryController = loader.getController();

primaryStage.setTitle("Hello World");
primaryStage.setScene(new Scene(root, 300, 275));
primaryStage.show();

final Task<DataModel> task = new Task<DataModel>(){
@Override
protected DataModel call() throws Exception
{
updateProgress(0, 3);
DataModel dataModel = new DataModel();
dataModel.loadListViewData();
Thread.sleep(2000);
updateProgress(1, 3);
dataModel.loadComoBoxData();
Thread.sleep(2000);
updateProgress(2, 3);
dataModel.loadTextAreaData();
Thread.sleep(2000);
updateProgress(3, 3);
Thread.sleep(1000);

return dataModel;
}
};

task.setOnSucceeded((event) -> {
try
{
FXMLLoader secondaryLoader = new FXMLLoader(getClass().getResource("secondary.fxml"));
Stage secondaryStage = new Stage();
Parent secondaryRoot = secondaryLoader.load();
SecondaryController secondaryController = secondaryLoader.getController();
secondaryController.initModel(task.getValue());
secondaryStage.setTitle("Scene One");
secondaryStage.setScene(new Scene(secondaryRoot, 500, 500));
secondaryStage.show();
primaryStage.close();
} catch (IOException e)
{
e.printStackTrace();
}

});

primaryController.getPBSplashValue().progressProperty().bind(task.progressProperty());
primaryController.getPISplash().progressProperty().bind(task.progressProperty());

new Thread(task).start();
}

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

}

主 Controller /启动画面

import javafx.fxml.FXML;
import javafx.scene.control.ProgressBar;
import javafx.scene.control.ProgressIndicator;

public class PrimaryController
{
@FXML
ProgressBar pbSplash;
@FXML
ProgressIndicator piSplash;


public ProgressBar getPBSplashValue()
{
return pbSplash;
}

public ProgressIndicator getPISplash()
{
return piSplash;
}

}

PrimaryFXML

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

<?import javafx.scene.control.ProgressBar?>
<?import javafx.scene.control.ProgressIndicator?>
<?import javafx.scene.layout.StackPane?>
<?import javafx.scene.layout.VBox?>

<StackPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.141" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sed.test.maventtestproject.PrimaryController">
<children>
<VBox maxHeight="-Infinity" maxWidth="-Infinity">
<children>
<ProgressBar fx:id="pbSplash" prefWidth="200.0" progress="0.0" />
<ProgressIndicator fx:id="piSplash" progress="0.0" />
</children>
</VBox>
</children>
</StackPane>

SecondayController/FirstSceneAfterSplashScreen

import javafx.fxml.FXML;
import javafx.scene.control.ComboBox;
import javafx.scene.control.ListView;
import javafx.scene.control.TextArea;

public class SecondaryController {
@FXML ListView<String> lvMain;
@FXML ComboBox<String> cbMain;
@FXML TextArea taMain;

private DataModel model ;

public void initModel(DataModel model) {
if (this.model != null) {
throw new IllegalStateException("Model can only be initialized once");
}
this.model = model ;

lvMain.setItems(this.model.getListViewData());
cbMain.setItems(this.model.getComboBoxData());
taMain.setText(this.model.getTextAreaData());
}
}

辅助FXML

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

<?import javafx.geometry.Insets?>
<?import javafx.scene.control.ComboBox?>
<?import javafx.scene.control.ListView?>
<?import javafx.scene.control.TextArea?>
<?import javafx.scene.layout.VBox?>

<VBox alignment="CENTER" spacing="20.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sed.test.maventtestproject.SecondaryController">
<children>
<ListView fx:id="lvMain" prefHeight="200.0" prefWidth="200.0" />
<ComboBox fx:id="cbMain" prefWidth="150.0" />
<TextArea fx:id="taMain" prefHeight="200.0" prefWidth="200.0" wrapText="true" />
</children>
<padding>
<Insets bottom="20.0" left="20.0" right="20.0" top="20.0" />
</padding>
</VBox>

型号

import java.util.ArrayList;
import java.util.List;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;

/**
*
* @author blj0011
*/
public class DataModel
{
private final ObservableList<String> listViewData = FXCollections.observableArrayList();
private final ObservableList<String> comboBoxwData = FXCollections.observableArrayList();
private final StringProperty textAreaDataProperty = new SimpleStringProperty();

public DataModel()
{
}

public void loadListViewData()
{
listViewData.addAll(retrieveListViewDataFromDB());
}

public ObservableList<String> getListViewData()
{
return listViewData;
}

public void loadComoBoxData()
{
comboBoxwData.addAll(retrieveComboBoxDataFromDB());
}

public ObservableList<String> getComboBoxData()
{
return comboBoxwData;
}

public void loadTextAreaData()
{
textAreaDataProperty.set(retrieveTextAreaDataFromDB());
}

public StringProperty getTextAreaDataProperty()
{
return textAreaDataProperty;
}

public String getTextAreaData()
{
return textAreaDataProperty.get();
}


//Private methods that fake retrieving data from the database.
private List<String> retrieveListViewDataFromDB()
{
List<String> dataFromDB = new ArrayList();
for(int i = 0; i < 1000; i++)
{
dataFromDB.add(Integer.toString(i));
}

return dataFromDB;
}

private List<String> retrieveComboBoxDataFromDB()
{
List<String> dataFromDB = new ArrayList();
dataFromDB.add("A");
dataFromDB.add("B");
dataFromDB.add("C");
dataFromDB.add("D");
dataFromDB.add("E");
dataFromDB.add("F");

return dataFromDB;
}

private String retrieveTextAreaDataFromDB()
{
return "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.";
}
}

关于java - PreLoader 的多线程 - JavaFX,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59938519/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com