gpt4 book ai didi

单击按钮时 JavaFX 在新线程上运行任务

转载 作者:行者123 更新时间:2023-12-02 01:17:34 24 4
gpt4 key购买 nike

当在 JavaFX 中单击按钮时,我尝试检索 XLS 文件并将其加载到 TableView 中。我正在使用 Task 类和 ExecutorService 来启动新线程。我需要阅读器类可重用,但 FileChooser 没有显示。

这是我尝试编写一些并发代码。我想知道我做错了什么以及如何改进我的代码,因为一切都是事件驱动的?

Controller 类代码

public void retrieveCustomersFromXLS() {
try {
loader.setOnSucceeded(workerStateEvent -> {
File file = null;
try {
file = loader.get();
} catch (Exception e) {
e.printStackTrace();
}
if (file != null && file.exists()) {
reader.setWorkingFile(file);
executor.submit(reader);
}
});
reader.setOnSucceeded(workerStateEvent1 -> {
Object[][] XLSFile = new Object[0][];
try {
XLSFile = reader.get();
} catch (Exception e) {
e.printStackTrace();
}
if (XLSFile != null) {
tableInterface.setEntries(XLSFile);
tableInterface.setEntryType("customers");
executor.submit(tableInterface);
}
});
tableInterface.setOnSucceeded(workerStateEvent2 -> {
customerList = FXCollections.observableArrayList(tableInterface.getCustomerEntries());
column_customerReference.setCellValueFactory(new PropertyValueFactory<customers, Integer>("customerReference"));
column_customerName.setCellValueFactory(new PropertyValueFactory<customers, String>("customerName"));
column_customerAddress.setCellValueFactory(new PropertyValueFactory<customers, String>("customerAddress"));
column_customerPost.setCellValueFactory(new PropertyValueFactory<customers, Integer>("customerPost"));
column_customerRegion.setCellValueFactory(new PropertyValueFactory<customers, String>("customerRegion"));
column_customerID_DDV.setCellValueFactory(new PropertyValueFactory<customers, String>("customerDDV"));
table_customerImports.setItems(customerList);
});
executor.submit(loader);
} catch (Exception e) {
e.printStackTrace();
}
}

阅读器类文件

@Override
protected File call() throws Exception {
FileChooser fileChooser = new FileChooser();
fileChooser.setTitle("Choose Excel file");
fileChooser.getExtensionFilters().addAll(new FileChooser.ExtensionFilter("Excel", "*.xlsx", "*.xls", "*.csv"));
File selectedFile = fileChooser.showOpenDialog(new Stage());
if (selectedFile != null) {
path = selectedFile.getAbsolutePath();
file = new File(path);
}
return file;
}

最佳答案

您必须在 JavaFX 应用程序线程上调用 FileChooser#showXXXDialog 方法。如果您发现任务失败,您将看到一个 IllegalStateException ,其中包含一条消息,说明您尝试在错误的线程上执行操作。此外,您不需要后台任务来提示用户输入文件。

下面是提示用户输入文本文件、在 Task 中读取文本文件并将结果放入 ListView 中的示例。

App.java

package com.example;

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

public class App extends Application {

@Override
public void start(Stage primaryStage) throws IOException {
Scene scene = new Scene(FXMLLoader.load(getClass().getResource("/App.fxml")));
primaryStage.setScene(scene);
primaryStage.setTitle("FileChooser Example");
primaryStage.show();
}

}

App.fxml

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

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

<VBox xmlns="http://javafx.com/javafx/13" xmlns:fx="http://javafx.com/fxml/1" spacing="5" prefWidth="600"
prefHeight="400" alignment="CENTER" fx:controller="com.example.Controller">
<padding>
<Insets topRightBottomLeft="5"/>
</padding>
<Button text="Open File..." onAction="#handleOpenFile"/>
<Separator/>
<ListView fx:id="listView" VBox.vgrow="ALWAYS"/>
</VBox>

Controller.java

package com.example;

import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import javafx.collections.FXCollections;
import javafx.concurrent.Task;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.ListView;
import javafx.stage.FileChooser;
import javafx.stage.FileChooser.ExtensionFilter;

public class Controller {

private final Executor executor = Executors.newSingleThreadExecutor(r -> {
Thread t = new Thread(r, "controller-thread");
t.setDaemon(true);
return t;
});

@FXML private ListView<String> listView;

@FXML
private void handleOpenFile(ActionEvent event) {
event.consume();

FileChooser chooser = new FileChooser();
chooser.getExtensionFilters()
.add(new ExtensionFilter("Text Files", "*.txt", "*.json", "*.xml", "*.html", "*.java"));

File file = chooser.showOpenDialog(listView.getScene().getWindow());
if (file != null) {
ReadFileTask task = new ReadFileTask(file.toPath());
task.setOnSucceeded(wse -> listView.setItems(FXCollections.observableList(task.getValue())));
task.setOnFailed(wse -> task.getException().printStackTrace());
executor.execute(task);
}
}

private static class ReadFileTask extends Task<List<String>> {

private final Path file;

private ReadFileTask(Path file) {
this.file = Objects.requireNonNull(file);
}

@Override
protected List<String> call() throws Exception {
return Files.readAllLines(file);
}

}

}

关于单击按钮时 JavaFX 在新线程上运行任务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58311110/

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