JavaFx - Kopiervorgang in TextField ausgeben

odbvirus

Neues Mitglied
Guten tag

Ich möchte in Java den Kopiervorgang von Ordner und Dateien in einer TextArea ausgeben lassen:
In der TextArea sollte also ausgegeben werden was kopiert wurde und zwar schritt für schritt als Liste.
Als Beispiel - Wie bei einem Setup, wo angezeigt wird, welche Dateien eben grade Installiert wurden.

Durch den DirectoryChooser wird erst gewählt, in welches Verzeichnis die Ordner und Dateien kopiert werden sollen:

Versucht habe ich folgendes Beispiel:

DirectoryChooser:
@FXML
private void browseClick(ActionEvent event) {

  Stage stage = (Stage)browseClick.getScene().getWindow();
  DirectoryChooser directoryChooser = new DirectoryChooser();
  File selectedDirectory = directoryChooser.showDialog(primaryStage);

  if (selectedDirectory == null) {
    chosenDirectory.setText("No Directory selected");
  } else {
    chosenDirectory.setText(selectedDirectory.getAbsolutePath());
    chosenDirectory.getText();
    pfad = chosenDirectory.getText();
  }
}

Kopiervorgang mit Ausgabe an TextArea:
@FXML
private void installClick(ActionEvent event) throws Exception {

  File src = new File("src/application/zip");
  File dest = new File(pfad);

  FileUtils.copyDirectory(src, dest);

  //------------------------------------------------------- Folder & File Scanner

  try (Stream<Path> walk = Files.walk(Paths.get(pfad + "/test"))) {
    List<String> result = walk.filter(Files::isRegularFile).map(x -> x.toString() + "\n").collect(Collectors.toList());

    try (Stream<Path> walk2 = Files.walk(Paths.get(pfad + "/test"))) {
      List<String> result2 = walk2.filter(Files::isDirectory).map(x -> x.toString() + "\n").collect(Collectors.toList());
      progressTextField.setText(result2.toString().replace(",", "").replace("[", "").replace("]", "").replace(" ", "") +
                                result.toString().replace(",", "").replace("[", "").replace("]", "").replace(" ", ""));
    }
  } catch (IOException e) {
    e.printStackTrace();
  }


Leider wird mir da nur ausgegeben was momentan in dem Ordner vorhanden ist.
Wenn der Kopiervorgang länger dauert, und neue Dateien hinzugefügt werden, wird nicht upgedated, was leider nicht der sinn ist.
Durch die Ausgabe sollte dem User der Fortschritt mitgeteilt werden.

ps. Hoffe ich poste es am richtigen Ort, wenn nicht bitte verschieben :)

Gruss odbvirus
 

Rushh0ur

Neues Mitglied
Deine installClick Funktion läuft auf einem sogenannten 'UI Thread' oder auch Main Thread, dh. alle UI Update Funktionen wie setText etc. werden erst ausgeführt, wenn deine Funktion beendet wird. Von daher dein beobachtetes Verhalten, dass nur die letzte Änderung sichtbar ist.

Du musst deine Kopierroutine in einem eigenen Thread ausführen. Dabei musst du jedoch beachten, dass du deine UI daraus nicht updaten kannst und die ganzen Aufrufe in eine runLater Methode wrappen musst.

Wichtig ist auch, dass wenn du deine Sachen in einem weiterem Thread ausführst, dann ist es Möglich, dass der Benutzer nochmal auf den Button klickt bzw. das Event dafür auslöst. Von daher solltest du dies verhindern in dem du z. B. diesen Button vor und nach der Aktion ein- und ausschaltest.

Hier mal ein Ansatz (nicht getestet):

Java:
private void installClick(ActionEvent event) throws Exception {
  // disable install button, to prevent further invocations by the user while the task is running

  Task<boolean> task = new Task<boolean>() {
    @Override
    public boolean call() {
      // long running task following

      File src = new File("src/application/zip");
      File dest = new File(pfad);

      FileUtils.copyDirectory(src, dest);

      //------------------------------------------------------- Folder & File Scanner
      try (Stream<Path> walk = Files.walk(Paths.get(pfad + "/test"))) {
        List<String> result = walk.filter(Files::isRegularFile).map(x -> x.toString() + "\n").collect(Collectors.toList());

        try (Stream<Path> walk2 = Files.walk(Paths.get(pfad + "/test"))) {
          List<String> result2 = walk2.filter(Files::isDirectory).map(x -> x.toString() + "\n").collect(Collectors.toList());

          // update ui, invoke the code on the main thread
          Platform.runLater(new Runnable() {
            @Override
            public void run() {
              // update ui
              progressTextField.setText(result2.toString().replace(",", "").replace("[", "").replace("]", "").replace(" ", "") +
                                        result.toString().replace(",", "").replace("[", "").replace("]", "").replace(" ", ""));
            }
          });
        }
      } catch (IOException e) {
        e.printStackTrace();
        return false;
      }

      // end of long running task

      return true;
    }
  };

  task.setOnSucceeded(e -> {
    boolean result = task.getValue();

    // do something with result

    Platform.runLater(new Runnable() {
      @Override
      public void run() {
        // enable install button, update ui
      }
    });
  });

  new Thread(task).start();
}
 
Zuletzt bearbeitet:
Oben Unten