JavaFX TreeView - TreeItem - SelectedItem

MasterQ

Mitglied
Moin,

ich bastele mit JavaFX einen TreeView. Die einzenen TreeItems sollen editierbare Strings sein.

Ich habe erstmal mit TreeItem<String> angefangen, um die Grundstrukturen zu erlernen. Ich frage bei Druck auf einen Button das ausgewählte Item ab und erledige die zugehörigen Aufgaben wie Knoten nach oben schieben oder die Tiefe eines Knoten verändern.

Da alles funktioniert, bin ich jetzt bei TreeItem<TextField> und muss feststellen, dass bei Auswahl eines Knotens mit der Maus, das Textfeld zwar den Fokus erhält und in den Edit-Modus geht, das SelectedItem des Baumes aber null bleibt.

Warum denn das?

Wie muss ich denn die Baumansicht aufbauen, dass die Knotentexte editierbar sind und aber auch das Auswählen registriert und entsprechend das SelectedItem gesetzt wird?

Ich bin bissl überrascht, dass das nicht geht. Die Baumansicht ist der Inhalt eines Tabs in einem TabPanel und ich agiere dabei voll mit Code Behind, da Tab- und Knotenanzahl der darzustellenden Bäume unterschiedlich und auch dynamisch sind.

Was übersehe ich?

Gruß

Joachim
 

mihe7

Top Contributor
Mal schauen, was ChatGPT meint (alle Antworten sind von ChatGPT - unkorrigiert).

1. zu "Warum denn das?"

Das liegt daran, dass ein TreeItem<TextField> ein anderes equals()-Verhalten aufweist als ein TreeItem<String>. Wenn Sie ein TreeItem<String>-Objekt mit einem anderen vergleichen, wird der Inhalt der String-Objekte verglichen. Wenn Sie jedoch ein TreeItem<TextField>-Objekt mit einem anderen vergleichen, wird die Speicheradresse des Objekts verglichen.
Wenn Sie also ein TreeItem<TextField>-Objekt mit einem anderen vergleichen möchten, müssen Sie sicherstellen, dass die beiden Objekte auf die gleiche Speicheradresse verweisen. Dies kann durch Überschreiben der equals()-Methode des TreeItem<TextField>-Objekts erreicht werden.
Ein weiterer möglicher Ansatz ist, den TextField-Inhalt beim Klicken auf ein TreeItem<TextField>-Objekt in ein temporäres TreeItem<String>-Objekt zu kopieren und dieses temporäre Objekt auszuwählen. Auf diese Weise können Sie sicherstellen, dass der equals()-Vergleich ordnungsgemäß funktioniert.
Ich hoffe, das hilft Ihnen weiter!

2. Wie muss ich denn die Baumansicht aufbauen, dass die Knotentexte editierbar sind und aber auch das Auswählen registriert und entsprechend das SelectedItem gesetzt wird?

Um editierbare Knotentexte in Ihrem TreeView zu ermöglichen und gleichzeitig das Auswählen von Knoten zu registrieren, können Sie die TreeView- und TreeItem-Klassen von JavaFX verwenden.

Sie können den TreeItem-Konstruktor verwenden, der einen TextField als Parameter akzeptiert, um ein editierbares TreeItem-Objekt zu erstellen. Wenn der Benutzer den Text im TextField ändert, wird auch der Text des TreeItem geändert.

Um das Auswählen von Knoten zu registrieren, können Sie einen Listener auf die selectionProperty() des TreeView setzen. Der Listener wird aufgerufen, wenn ein Knoten ausgewählt wird, und Sie können das ausgewählte TreeItem aus der selectedItemProperty() des TreeView abrufen.

Hier ist ein Beispielcode, der Ihnen den grundlegenden Ansatz zeigen soll:
Java:
TreeView<String> treeView = new TreeView<>();

// Baumstruktur aufbauen
TreeItem<String> root = new TreeItem<>("Root");
root.setExpanded(true);

TreeItem<String> child1 = new TreeItem<>("Child 1");
root.getChildren().add(child1);

TreeItem<String> child2 = new TreeItem<>("Child 2");
root.getChildren().add(child2);

treeView.setRoot(root);

// TreeView-Selection registrieren
treeView.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> {
    if (newValue != null) {
        System.out.println("Selected: " + newValue.getValue());
    }
});

// Editierbare TreeItems erstellen
TreeItem<String> editableItem = new TreeItem<>("Editable Node");
editableItem.setGraphic(new TextField(editableItem.getValue()));
editableItem.getValue(); // gibt den Text des TreeItems zurück
editableItem.getValue(); // gibt das TextField-Objekt zurück

child1.getChildren().add(editableItem);

In diesem Beispiel wird ein TreeView-Objekt erstellt, dem ein Wurzel-TreeItem-Objekt hinzugefügt wird. Dann werden zwei weitere TreeItem-Objekte als Kinder des Wurzel-TreeItems hinzugefügt.

Dann wird ein editierbares TreeItem-Objekt erstellt, indem ein TextField-Objekt als Grafik des TreeItems gesetzt wird. Dieses TreeItem wird als Kind des ersten Kind-TreeItems hinzugefügt.

Schließlich wird ein Listener auf die selectedItemProperty() des TreeView gesetzt, um das ausgewählte TreeItem zu registrieren. Wenn der Benutzer ein TreeItem auswählt, wird der Name des Knotens in der Konsole ausgegeben.

Ich hoffe, das hilft Ihnen weiter!

3. zu "Was übersehe ich"?

Es tut mir leid, wenn meine vorherige Antwort nicht direkt auf Ihre Anforderungen zutraf. Es ist tatsächlich möglich, die Baumansicht mit editierbaren Knotentexten zu erstellen und gleichzeitig das Auswählen von Knoten zu registrieren. Hier ist ein Beispielcode, der Ihnen helfen soll:
Java:
TreeView<String> treeView = new TreeView<>();

// Baumstruktur aufbauen
TreeItem<String> root = new TreeItem<>("Root");
root.setExpanded(true);

TreeItem<String> child1 = new TreeItem<>("Child 1");
root.getChildren().add(child1);

TreeItem<String> child2 = new TreeItem<>("Child 2");
root.getChildren().add(child2);

treeView.setRoot(root);

// TreeView-Selection registrieren
treeView.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> {
    if (newValue != null) {
        System.out.println("Selected: " + newValue.getValue());
    }
});

// Editierbare TreeItems erstellen
TreeItem<String> editableItem = new TreeItem<>("Editable Node");
editableItem.setGraphic(new TextField(editableItem.getValue()));
editableItem.getValue(); // gibt den Text des TreeItems zurück
editableItem.getValue(); // gibt das TextField-Objekt zurück

child1.getChildren().add(editableItem);

In diesem Beispiel wird ein TreeView-Objekt erstellt und ein Wurzel-TreeItem-Objekt hinzugefügt. Dann werden zwei weitere TreeItem-Objekte als Kinder des Wurzel-TreeItems hinzugefügt.

Als Nächstes wird ein editierbares TreeItem-Objekt erstellt, indem ein TextField-Objekt als Grafik des TreeItems gesetzt wird. Das TreeItem wird als Kind des ersten Kind-TreeItems hinzugefügt.

Schließlich wird ein Listener auf die selectedItemProperty() des TreeView gesetzt, um das ausgewählte TreeItem zu registrieren. Wenn der Benutzer ein TreeItem auswählt, wird der Name des Knotens in der Konsole ausgegeben.

Ich hoffe, das hilft Ihnen weiter! Wenn Sie weitere Fragen haben, stehe ich gerne zur Verfügung.
 

MasterQ

Mitglied
<Ironie>
hm, net schlecht. Forum ade, willkommen chatGPT. :eek:
</Ironie>

Die Antwort scheint mir nicht korrekt, so die Kommentare zu den Zeilen 25 und 26. Gleicher Code aber unterschiedliche Erklärungen zum Verhalten.

Auch ob der Hinweis auf equals zielführend ist ? Eigentlich sind hier keine zwei unterschiedliche Instanzen im Spiel, oder? Es geht doch darum, dass nach der Auswahl eines Knoten die Eigenschaft SelectedItem nicht gesetzt wird. Dazu wird keine zweite Instanz benötigt. Ich wüsste auch nicht wozu da was verglichen werden sollte.

<Plonk>, ab in die Tonne damit.
 

MasterQ

Mitglied
Schwer zu beantworten ohne Code
Ich wüsste nicht, was ich da für Code posten sollte, sry! Oder anders ausgedrückt, wie das hilfreich sein sollte.

die folgende Routine erzeugt eine Baumansicht. Lasse ich die Baumansicht anzeigen und wähle einen Eintrag aus, wird SelectedItem des Baumes nicht gesetzt und bleibt null. Mache is das gleiche aber anstatt mit TextField mit String, wird SelectedItem gesetzt.

Java:
    private void initfortest() {

        TreeItem root = new TreeItem<TextField>(new TextField("Wurzel"));


        for (int i = 0; i < 10; ++i) {
            root.getChildren().add(new TreeItem<TextField>( new TextField(String.format("Kind %04d", i))));
        }

        var i = 0;
        for(var a  :  root.getChildren()){
            ((TreeItem<TextField>) a).getChildren().add(new TreeItem<TextField>(new TextField(String.format("Enkel %4d", i++))));
        }

        this.setRoot(root);
        this.setShowRoot(false);

    }

Das war's schon. Mehr kann ich nicht zeigen, weil es mehr nicht gibt.
 

mihe7

Top Contributor
Das hängt vermutlich einfach damit zusammen, wie Du das Item wählst. Klickst Du in das Textfeld wird der Knoten nicht gewählt, klickst Du etwas links daneben, sieht es so aus:
1680372070057.png
Und dann wird auch korrekterweise auch
1680372102025.png
angezeigt.

Code dazu:
Java:
public class App extends Application {

    @Override
    public void start(Stage stage) {
        TreeItem<TextField> root = new TreeItem<>(new TextField("Wurzel"));
        
       for (int i = 0; i < 10; ++i) {
            root.getChildren().add(new TreeItem<TextField>( new TextField(String.format("Kind %04d", i))));
        }
       
        int i = 0;
        for(var a  :  root.getChildren()){
            ((TreeItem<TextField>) a).getChildren().add(new TreeItem<TextField>(new TextField(String.format("Enkel %4d", i++))));
        }
        
        TreeView<TextField> treeView = new TreeView<>(root);
        treeView.setShowRoot(false);
        
        Button button = new Button("Show");
        button.setOnAction(eh -> {
            TreeItem<TextField> selectedItem = treeView.getSelectionModel().getSelectedItem();
            String text = selectedItem == null ? "Nichts gewählt" :
                    "Text: " + selectedItem.getValue().getText();
            
            Alert alert = new Alert(INFORMATION);
            alert.setContentText(text);
            alert.showAndWait();
        });
        
        ScrollPane scrollable = new ScrollPane(treeView);
        VBox content = new VBox(scrollable, button);
        
        var scene = new Scene(content, 640, 480);
        stage.setScene(scene);
        stage.show();
    }

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

}
 

MasterQ

Mitglied
ah, das hatte ich ausprobiert. Anscheinend hab ich dabei nie den richtigen Spot erwischt. * ärger *

Jetzt muss ich ausbaldovern, wie ich das hinbiegen kann, dass ich das Auswählen, d.h. den Erhalt des Fokus beim Textfeld abfangen und des SelectedItem wohl per Hand setzen kann.

Geht das dann über das zugehörige TextCell? Ich habe da noch nie nix mit gemacht.
 

mihe7

Top Contributor
Beispielsweise könnte man es so versuchen:

Java:
public class App extends Application {

    @Override
    public void start(Stage stage) {
        TreeItem<TextField> root = new TreeItem<>(new TextField("Wurzel"));

        Map<TextField, TreeItem<TextField>> tree = new HashMap<>();

        for (int i = 0; i < 10; ++i) {
            TextField tf = new TextField(String.format("Kind %04d", i));
            TreeItem<TextField> item = new TreeItem<>(tf);
            tree.put(tf, item);
            root.getChildren().add(item);
        }

        int i = 0;
        for (var a : root.getChildren()) {
            TextField tf = new TextField(String.format("Enkel %04d", i++));
            TreeItem<TextField> item = new TreeItem<>(tf);
            tree.put(tf, item);
            ((TreeItem<TextField>) a).getChildren().add(item);
        }

        TreeView<TextField> treeView = new TreeView<>(root);
        treeView.setShowRoot(false);

        Button button = new Button("Show");
        button.setOnAction(eh -> {
            TreeItem<TextField> selectedItem = treeView.getSelectionModel().getSelectedItem();
            String text = selectedItem == null ? "Nichts gewählt"
                    : "Text: " + selectedItem.getValue().getText();

            Alert alert = new Alert(INFORMATION);
            alert.setContentText(text);
            alert.showAndWait();
        });

        ScrollPane scrollable = new ScrollPane(treeView);
        VBox content = new VBox(scrollable, button);

        var scene = new Scene(content, 640, 480);
        scene.focusOwnerProperty().addListener((ov, oldValue, newValue) -> {
            TreeItem<TextField> item = tree.get(newValue);
            if (item != null) {
                treeView.getSelectionModel().select(item);
            }
        });
        stage.setScene(scene);
        stage.show();
    }

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

}
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
W JavaFX JavaFX - TreeView will nicht AWT, Swing, JavaFX & SWT 8
ProggersWorld JavaFX Icons im TreeView werden nicht angezeigt AWT, Swing, JavaFX & SWT 1
L JavaFX TreeView aufstellen läuft irgendwie auf Endlosschleife AWT, Swing, JavaFX & SWT 3
L JavaFX TreeView Edit Mode über F2 AWT, Swing, JavaFX & SWT 13
ralfb1105 JavaFX TreeView dynamisch aus Datenbank Tabelle erstellen AWT, Swing, JavaFX & SWT 22
B JavaFx TreeView mit file system AWT, Swing, JavaFX & SWT 1
D JavaFX TreeView stylen AWT, Swing, JavaFX & SWT 6
L JavaFX TreeView mit File Objects AWT, Swing, JavaFX & SWT 0
P TreeView automatisch an große von Inhalt anpassen AWT, Swing, JavaFX & SWT 3
P X extends TreeView - eigene Methoden AWT, Swing, JavaFX & SWT 5
I JavaFX Im TreeView, TreeItems sortieren AWT, Swing, JavaFX & SWT 3
B TreeView cellFactory AWT, Swing, JavaFX & SWT 4
D javafx.scene.control.TreeView als dropdown Menü AWT, Swing, JavaFX & SWT 6
K JavaFX Mehrere Cell Editors in einem TreeView Item AWT, Swing, JavaFX & SWT 2
I JavaFX TreeView Pfeil nicht mehr Klickbar machen AWT, Swing, JavaFX & SWT 1
B JavaFX Wie Treeview aus xml erzeugen AWT, Swing, JavaFX & SWT 11
B Convert Treeview to XML AWT, Swing, JavaFX & SWT 9
N JavaFX TreeView mit verschiedenen Datentypen AWT, Swing, JavaFX & SWT 8
C SWT Treeview mit Bilder im Label verändert Expanded Icon AWT, Swing, JavaFX & SWT 1
agent47 JavaFX TreeView Struktur dynamisch einlesen AWT, Swing, JavaFX & SWT 1
Tom299 JavaFX TreeView Expanded-Icon ändern AWT, Swing, JavaFX & SWT 0
ToBJo JavaFX TreeView zerstört sich selbst AWT, Swing, JavaFX & SWT 1
G JavaFX TreeView stylen AWT, Swing, JavaFX & SWT 2
G JavaFX TreeView AWT, Swing, JavaFX & SWT 3
G Problem mit TreeView AWT, Swing, JavaFX & SWT 2
L TreeViewerColumn - gesamte TreeView-breite nutzen? AWT, Swing, JavaFX & SWT 5
T SWT Treeview größe ändern AWT, Swing, JavaFX & SWT 2
C SWT Error/Warnings in TreeView AWT, Swing, JavaFX & SWT 2
P Eindeutiger Knoten im Treeview AWT, Swing, JavaFX & SWT 3
K SystemIcons v. Dateien & Verz. im TreeView anzeigen AWT, Swing, JavaFX & SWT 2
P JavaFX Key-Value-Paar auf TreeItem ermitteln AWT, Swing, JavaFX & SWT 6
M JavaFX JAVAFX TreeItem mit Tooltip versehen AWT, Swing, JavaFX & SWT 4
N JavaFX TreeItem: Value-Binding AWT, Swing, JavaFX & SWT 1
S JavaFX TreeItem: Icon am Ende eines Eintrags anhängen AWT, Swing, JavaFX & SWT 2
G JavaFX TreeItem AWT, Swing, JavaFX & SWT 3
Madlip Probleme mit TreeItem AWT, Swing, JavaFX & SWT 2
K SWT und Tree, wie kann ich TreeItem aus einem Tree entfernen? AWT, Swing, JavaFX & SWT 12
T [SWT] TreeItem als selektiert markieren AWT, Swing, JavaFX & SWT 2
G SWT - TreeItem mit Image AWT, Swing, JavaFX & SWT 4
M Swing ComboBox ein SelectedItem übergeben/anzeigen AWT, Swing, JavaFX & SWT 7
F ComboBox selectedItem setzen AWT, Swing, JavaFX & SWT 10

Ähnliche Java Themen

Neue Themen


Oben