JavaFX запускает задачи в новых потоках при нажатии кнопки - PullRequest
0 голосов
/ 09 октября 2019

Я пытаюсь получить файл XLS и загрузить его в TableView при нажатии кнопки в JavaFX. Я использую класс Task и ExecutorService для запуска новых потоков. Мне нужно, чтобы класс читателя можно было использовать повторно, но FileChooser не появляется.

Это моя попытка написания некоторого параллельного кода. Я хотел бы знать, что я делаю неправильно и как бы я улучшил свой код, поскольку все зависит от событий?

Код класса контроллера

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;
    }

1 Ответ

2 голосов
/ 10 октября 2019

Вы должны вызывать методы FileChooser#showXXXDialog в потоке приложений JavaFX . Если вы заметили, что ваша задача не выполнена, вы бы увидели 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);
    }

  }

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...