Jetzt anmelden...

Login
Passwort
Registrieren
30.08.21 167 Views Kommentare [0] 0 0

credit: ©Sergey Nivens

JAVA Tutorial #56

JavaFX ListView

Mit dem JavaFX Control-Node ListView kannst du Objekte einer Datensammlung optisch in Listenform darstellen. Im Gegensatz zu einem Menu ermöglicht die ListView sowohl eine Mehrfachauswahl als auch das Editieren der Elemente durch Doppelklick.

Download als eBook

Schnelles Code-Beispiel

ListView<String> listview = new ListView<>();
listview.getItems().addAll("Eins", "Zwei", "Drei", "Vier");

VBox layout = new VBox();
layout.getChildren().addAll(listview);
Scene scene = new Scene(layout, 300, 200);
primaryStage.setScene(scene);
primaryStage.show();                

Was ist eine ListView?

Mit dem JavaFX Control-Node ListView kannst du Objekte einer Datensammlung optisch in Listenform darstellen. Es wird durch die Klasse javafx.scene.control.ListView repräsentiert.

Im Gegensatz zu einem Menu ermöglicht die ListView sowohl eine Mehrfachauswahl als auch das Editieren der Elemente durch Doppelklick.

In JavaFX sieht eine ListView so aus:

Java JavaFX ListView

ListView und ObservableList

Die einzelnen Elemente werden aber nicht in der ListView selbst gespeichert. Stattdessen ist in der ListView eine ObservableList verbaut, die für die eigentliche Verwaltung der einzelnen Elemente zuständig ist.

Die ListView ist dabei das GUI-Steuerungselement: Sobald über die ListView ein Element hinzugefügt, geändert oder gelöscht wird, erkennt das die ObservableList und führt die entsprechende Änderung dann auch tatsächlich in der Sammlung durch.

Insofern "überwacht" (engl. "observe") die ObservableList die ListView.

Die Klasse ListCell

Zur Darstellung der einzelnen Zellen und Repräsentation der Elemente aus der ObservableList verwendet die ListView die Klasse ListCell. Die jeweiligen ListCell-Objekte werden wiederum durch eine cell factory erstellt.

Die ListView im Einsatz

ListView erstellen

Die ListView ist eine generische Klasse. Das bedeutet, dass wir einen Typ-Parameter in spitzen Klammern angeben müssen. Der Typ-Parameter legt fest, welche Art von Elementen die ListView aufnehmen kann.

Für unser Beispiel wählen wir eine ListView aus Strings:

ListView<String>listview = new ListView<>();                

Objekte hinzufügen

Mit der Methode add() lassen sich der Liste Elemente hinzufügen. Hier ein Beispiel:

listview.getItems().add("Eins");
listview.getItems().add("Zwei");
listview.getItems().add("Drei");
listview.getItems().add("Vier");                

Mit der Methode addAll() kannst du Elemente in nur einer Anweisung hinzufügen:

listview.getItems().addAll("Eins", "Zwei", "Drei", "Vier");                

Mehrfachauswahl aktivieren

Die ausgewählten Elemente werden von einem SelectionModel verwaltet. Dabei erlaubt die ListView auch die Auswahl von mehreren Elementen gleichzeitig (STRG auf Windows, CMD auf MacOS). Standardmäßig ist der Auswahlmodus (SelectionMode) aber auf SINGLE gestellt.

Um die Mehrfachauswahl zu aktivieren, holst du dir das SelectionModel mit getSelectionModel() und änderst den SelectionMode auf MULTIPLE:

listview.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);                

Selektierte Elemente auslesen

Um die vom User selektierten Elemente auszulesen, rufen wir auf dem SelectionModel die Methode getSelectedItems() auf. Der Rückgabetyp der Methode ist eine ObservableList mit allen Elementen der Sammlung:

ObservableList<String> auswahl = listview.getSelectionModel().getSelectedItems();                

Mit einer for-Schleife können wir nun durch die einzelnen Elemente iterieren. Hier der entsprechende Code inklusive einem Button, der das Prozedere in Gang setzt:

Button btn = new Button("Was ist ausgewählt?");
btn.setOnAction( e -> {
    ObservableList<String> auswahl = listview.getSelectionModel().getSelectedItems();
    for(String sV : auswahl){
        System.out.println(sV);
    }
});                

Elemente editieren

Manchmal ist es praktisch, dass der User den gespeicherten Wert einer Zelle ändern kann:

Java JavaFX ListView editierbar

Das lässt sich einfach umsetzen, indem wir zuerst die grundsätzliche Editierbarkeit der ListView einschalten. Anschließend müssen wir sicherstellen, dass die Cell Factory editierbare Zellen unterstützt:

listview.setEditable(true);
listview.setCellFactory(TextFieldListCell.forListView());                

Bei einem Doppelklick kann der User nun der Text ändern und mit ENTER die Eingabe bestätigen. Die ObservableList checkt das sofort und aktualisiert die Sammlung automatisch.

Vollständiger Code

Hier der vollständige Code für unser Beispiel:

import javafx.application.Application;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ListView;
import javafx.scene.control.SelectionMode;
import javafx.scene.control.cell.TextFieldListCell;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;


public class H1_ListView extends Application {

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

    @Override
    public void start(Stage primaryStage) throws Exception {

        ListView<String> listview = new ListView<>();
        listview.getItems().addAll("Eins", "Zwei", "Drei", "Vier");
        listview.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);

        listview.setEditable(true);
        listview.setCellFactory(TextFieldListCell.forListView());

        Button btn = new Button("Was ist ausgewählt?");
        btn.setOnAction( e -> {
            ObservableList<String> auswahl = listview.getSelectionModel().getSelectedItems();
            for(String sV : auswahl){
                System.out.println(sV);
            }
        });

        VBox layout = new VBox();
        layout.getChildren().addAll(listview, btn);
        Scene scene = new Scene(layout, 300, 200);
        primaryStage.setScene(scene);
        primaryStage.show();
    }
}                

Mehr Datentypen für ListView

In unserem Beispiel oben haben wir ganz brav mit Strings gearbeitet. Selbstverständlich können wir aber alle Objekttypen in die ListView bzw. die ObservableList aufnehmen. Das ist ja gerade der Sinn von generischen Klassen 🥰

Eigene Objekttypen

Das solltest du in diesem Zusammenhang wissen:

  • Innerhalb einer ListView ruft die ListCell automatisch die toString()-Methode der gespeicherten Objekte. Der Rückgabewert wird dann in der Zelle entsprechend angezeigt.

Für die Darstellung in der ListView ist also nur die toString()-Methode des Gesamt-Elements relevant.

Sehen wir uns jetzt ein entsprechendes Beispiel an, bei dem wir Objekte vom Typ Mitarbeiter in die ListView aufnehmen:

ListView<Mitarbeiter> listview = new ListView<>();
Mitarbeiter m1 = new Mitarbeiter("Luke Skywalker", 20);
Mitarbeiter m2 = new Mitarbeiter("Darth Vader", 40);
listview.getItems().addAll(m1, m2);

VBox layout = new VBox();
layout.getChildren().add(listview);
Scene scene = new Scene(layout, 300, 200);
primaryStage.setScene(scene);
primaryStage.show();

Und so wird es in JavaFX dargestellt:

Java JavaFX ListView toString

Hm... 🤔 Was wir hier angezeigt bekommen, ist die Speicherort-Adressen der beiden Objekte. Die dürften den Benutzer unseres Programms wohl kaum interessieren.

Der Grund für dieses Verhalten liegt darin, dass in der Klasse Mitarbeiter die toString()-Methode noch nicht überschrieben wurde und so wird der Standard-String zurückgeliefert.

Also überschreiben wir die toString()-Methode von Mitarbeiter kurzerhand einmmal:

public class Mitarbeiter {

    String name;
    int alter;
    char gehaltsklasse;

    public Mitarbeiter(String name, int alter){
        this.name = name;
        this.alter = alter;
        gehaltsklasse = 'B';
    }

    @Override
    public String toString(){
        return name;
    }

}                

Damit sieht das Ganze doch schon user-verträglicher aus:

Java JavaFX ListView toString

Einschränkung

Eine kleine Einschränkung gibt es allerdings: Es können nämlich keine ListView-Elemente durch Doppelklick editiert werden, die nicht vom Typ String sind: This method will only work on ListView instances which are of type String.

Falconbyte unterstützen

Kommentar schreiben

Alle Kommentare

Es gibt bislang noch keine Kommentare zu diesem Thema.

Objekte löschen

Wir wissen, wie wir Objekte erstellen können. Aber wie werden wir sie wieder los?

Objekte vergleichen

Was ist der Unterschied zwischen == und equals()?

Konstruktoren bei Vererbung

Trainieren Sie ihre Konstruktoren-Skills

FALCONBYTE.NET

Handmade with 🖤️

© 2018-2021 Stefan E. Heller

Impressum | Datenschutz

Falconbyte GitHub facebook programmieren lernen twitter programmieren lernen discord programmieren lernen