JavaFX TreeView mit verschiedenen Datentypen

Nemesys88

Bekanntes Mitglied
Guten Morgen zusammen!

Ich brauche mal dringend eure Hilfe:

Es geht um eine TreeView in der ich gerne Strings als Oberbegriffe speichern möchte, als Leafs/Blätter dann aber selbst erstellte Objekte habe.

Ich habe ein kleines Beispiel dazu erstellt, mit dem wir arbeiten können:

Java:
package application;
   
import javafx.application.Application;
import javafx.stage.Stage;
import javafx.util.Callback;
import javafx.scene.Scene;
import javafx.scene.control.TreeCell;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.scene.layout.StackPane;


public class Main extends Application {
   
    private TreeView<String> tree;
    private TreeItem<String> treeroot;
    private Product p1;
   
    @Override
    public void start(Stage primaryStage) {
        try {
            StackPane root = new StackPane();
           
            //Tree-root
            treeroot = new TreeItem<>();
            treeroot.setExpanded(true);
              
            //Create tree
            tree = new TreeView<>();
            tree.setRoot(treeroot);
            tree.setShowRoot(false); 
           
            TreeItem<String> kat1,kat2,kat3;
           
            kat1 = createNode("Kategorie 1", treeroot);
            kat2 = createNode("Kategorie 2", treeroot);
            kat3 = createNode("Kategorie 3", treeroot);
           
            p1 = new Product("Bleistift",0.80,20);
           
            //createLeaf(p1,kat1);
           
//            tree.setCellFactory(new Callback<TreeView<String>, TreeCell<String>>() {
//               
//                @Override
//                public TreeCell<String> call(TreeView<String> param) {
//                    // TODO Auto-generated method stub
//                    return null;
//                }
//            });
           
           
            root.getChildren().add(tree);
            Scene scene = new Scene(root,400,400);
            primaryStage.setScene(scene);
            primaryStage.show();
        } catch(Exception e) {
            e.printStackTrace();
        }
    }
   
//    private TreeItem<Product> createLeaf(Product p, TreeItem<String> parent) {
//        TreeItem<Product> node = new TreeItem<>(p.getName());
//        node.setExpanded(false);
//        parent.getChildren().add(node);
//        return node;
//    }

    public TreeItem<String> createNode(String titel, TreeItem<String> parent)
    {
        TreeItem<String> node = new TreeItem<>(titel);
        node.setExpanded(false);
        parent.getChildren().add(node);
        return node;
    }

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

Dazu gibt es eine Product-Klasse an der nichts weiter interessant ist:

Java:
package application;

public class Product {

    private String name;
    private double preis;
    private int anzahl;
   
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public double getPreis() {
        return preis;
    }
    public void setPreis(double preis) {
        this.preis = preis;
    }
    public int getAnzahl() {
        return anzahl;
    }
    public void setAnzahl(int anzahl) {
        this.anzahl = anzahl;
    }
   
    public Product(String name, double preis, int anzahl) {
        this.name = name;
        this.preis = preis;
        this.anzahl = anzahl;
    }
}

Wie ihr in der Main seht habe ich 3 Kategorien angelegt, alles normale Strings.
Und möchte jetzt in den Kategorien gerne Products speichern.

Im Prinzip ist das, was ich machen möchte jetzt eine createLeafs - Funktion (siehe auskommentierter Code).

Welche Möglichkeiten habe ich, so etwas zu machen ?

Nach einem ganzen Tag googlen und ausprobieren habe ich gestern eigentlich nur die Lösung Treecellfactory gefunden. Nur weiss ich beim besten Willen nicht, was ich in die Factory jetzt für einen Code reinschreiben muss, damit ich Produkte als Leafs speichern kann...

Gibt es evtl. noch eine einfachere Lösung ?

Wenn es die nicht gibt dann brauch ich bitte Hilfe bei der Factory.

P.s.: Ja, ich hab mir das Oracle-Beispiel angesehen, habe es aber nicht wirklich verstanden.

mfG
 

Tom299

Bekanntes Mitglied
Ich habe bei mir auch ein TreeView eingebaut. Habe aber schnell gemerkt, daß ich mit String nicht weit kommen und hab mir ein eigenes MenuItem (ich nutze ihn als Tree-Menü) Objekt erstellt. Die toString()-Methode enthält den angezeigten String und ansonsten hab ich halt noch zusätzliche Felder drin wie id oder fxml-name usw.
Vielleicht solltest du dir auch ein Übergeordnetes Objekt ausdenken, wo du dein Produkt reinstecken kannst, den Namen usw usf. Alternativ funktioniert sicher auch Object und dann immer mit instanceof checken und casten, find ich aber nicht so schön.
 

Nemesys88

Bekanntes Mitglied
Danke für deine Antwort, über die Möglichkeit mit Object habe ich auch schon nachgedacht und mich jetzt entschieden das so zu machen, auch wenn die Lösung nicht mega schön ist.

Vielleicht hat ja noch jemand eine bessere Idee.. ?!

Bis dahin würd ich das aber gerne so zum Laufen kriegen:

Java:
package application;
   
import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.scene.layout.StackPane;


public class Main extends Application {
   
    private TreeView<Object> tree;
    private TreeItem<Object> treeroot;
    private TreeItem<Object> node,kat1,kat2,kat3;
    private Product p1,p2,p3;
   
    @Override
    public void start(Stage primaryStage) {
        try {
            StackPane root = new StackPane();
           
            //Tree-root
            treeroot = new TreeItem<>();
            treeroot.setExpanded(true);
              
            //Create tree
            tree = new TreeView<>();
            tree.setRoot(treeroot);
            tree.setShowRoot(false); 
           
            kat1 = createNode("Kategorie 1", treeroot);
            kat2 = createNode("Kategorie 2", treeroot);
            kat3 = createNode("Kategorie 3", treeroot);
           
            p1 = new Product("Bleistift",0.80,20);
            p2 = new Product("Block",1.40,40);
            p3 = new Product("Buch",2.30,60);
           
            createNode(p1,kat1);
            createNode(p2,kat2);
            createNode(p3,kat3);
         
           
            root.getChildren().add(tree);
            Scene scene = new Scene(root,400,400);
            primaryStage.setScene(scene);
            primaryStage.show();
        } catch(Exception e) {
            e.printStackTrace();
        }
       
        tree.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<Object>() {

            @Override
            public void changed(ObservableValue<? extends Object> observable, Object oldValue, Object newValue) {
                   
                if (newValue instanceof Product)
                {
                    System.out.println(((Product) newValue).getName());
                    System.out.println(((Product) newValue).getPreis());
                    System.out.println(((Product) newValue).getAnzahl());
                }
                else if (newValue instanceof String)
                {
                    System.out.println(newValue);
                }
            }
        });
    }

    public TreeItem<Object> createNode(Object param, TreeItem<Object> parent)
    {
        if (param instanceof String)
        {
            node = new TreeItem<>(param);   
        }
        else if (param instanceof Product)
        {
            node = new TreeItem<>(((Product) param).getName());
        }
       
        node.setExpanded(false);
        parent.getChildren().add(node);
        return node;
    }

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

Er macht noch keine Ausgaben - kompiliert aber sauber. Wo sind evtl. noch Fehler ??
 

Nemesys88

Bekanntes Mitglied
Okay mir ist im ChangeListener schonmal aufgefallen das newValue ein TreeItem ist und das das deshalb so mit instanceof nicht funktioniert da muss dann eher sowas her: String val = ((TreeItem) newValue).getValue().getClass().getSimpleName(); und dann zb. switch (val) ...

Bei einer Testausgabe der val - Variable hab ich dann bemerkt, dass ich nicht 3x String + 3x Product gespeichert hab, sondern 6x String.

Bekomme es in der createNode() aber noch nicht hin korrekt Products zu speichern...
 
Zuletzt bearbeitet:

Nemesys88

Bekanntes Mitglied
Gut, jetzt speichert er die Products. Code:

Java:
        tree.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<Object>() {

            @Override
            public void changed(ObservableValue<? extends Object> observable, Object oldValue, Object newValue) {
              
                String val = ((TreeItem) newValue).getValue().getClass().getSimpleName();
                //System.out.println(val);
              
                switch (val)
                {
                case "Product":
                    Product p = new Product();
                    p = (Product) ((TreeItem) newValue).getValue();
                    System.out.println(p.getName());
                    System.out.println(p.getPreis());
                    System.out.println(p.getAnzahl());
                    break;
                  
                case "String":
                    break;
                  
                default:
                    break;
                }
              
            }
        });
    }

    public TreeItem<Object> createNode(Object param, TreeItem<Object> parent)
    {
        if (param instanceof String)
        {
            node = new TreeItem<>(param);  
        }
        else if (param instanceof Product)
        {
            node = new TreeItem<>(((Product) param));
        }
      
        node.setExpanded(false);
        parent.getChildren().add(node);
        return node;
    }

Das Einzige was jetzt noch fehlt ist der richtige Name im Baum...

Die Zeile node = new TreeItem<>(((Product) param)); führt dazu, dass im Baum der kryptische Name
"application.Product@320a270b" steht...

Wie bekomm ich da jetzt den richtigen Namen hin ? (der da wäre param.getName)

Wenn ich node.setGraphic(new Label(((Product) param).toString()));
mache gibt er "Bleistift application.Product..." an also den richtigen Begriff, aber auch das Falsche...

Und node.setLabel will er nicht weil es sich um nen Object handelt.

???
 
Zuletzt bearbeitet:

SeriousD0nkey

Bekanntes Mitglied
Wie Tom299 bereits geschrieben hat, kannst du die toString()-Methode in Products überschreiben und dort deinen gewünschten Wert zurückgeben. Damit müsstest du dies erreichen können, wenn ich mich jetzt nicht irre.
 

Nemesys88

Bekanntes Mitglied
Ah genau, ja! Vielen Dank nochmal an Alle.

Funktioniert jetzt alles soweit - in dem kleinen Beispiel. Jetzt muss ich das Ganze mal in meine komplexere Anwendung übertragen... :D

Kleine Frage noch am Rande:

In den Zeilen:

1) String val = ((TreeItem) newValue).getValue().getClass().getSimpleName();
und 2) p = (Product) ((TreeItem) newValue).getValue();

bekomme ich jetzt Warnings wegen RawTypes.. -> Eclipse bietet mir jetzt an:
"add @SurpressWarnings: 'rawtypes' to changed()"

also changed kommt von dem ChangeListener der am Tree hängt.

Kann ich das mit dem @ so machen, oder ist das schlechter Stil? Und wenn es schlechter Stil ist, wie schreibe ich die 2 Zeilen so, dass ich keine SurpressWarning mehr brauche ?
 

Christopher25

Bekanntes Mitglied
Ich weiß es ist schon ein alter Thread aber warum castet ihr das ganze im nachhinein?
Gibt das dem ChangeListener doch direkt mit, dafür sind Generics doch da^^

Java:
tree.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<TreeItem<?>>() {

            @Override
            public void changed(ObservableValue<? extends TreeItem<?>> observable, TreeItem<?> oldValue, TreeItem<?> newValue) {
           
                String val = newValue.getValue().getClass().getSimpleName();
                //System.out.println(val);
           
                switch (val)
                {
                case "Product":
                    Product p = new Product();
                    p = (Product) newValue.getValue();
                    System.out.println(p.getName());
                    System.out.println(p.getPreis());
                    System.out.println(p.getAnzahl());
                    break;
               
                case "String":
                    break;
               
                default:
                    break;
                }
           
            }
        });


Ach und warum den klassennamen als String wiedergeben lassen und dann den Klassennamen überprüfen wobei es doch die...

if (newValue.getValue() instanceof Product) {
.....
}

Variante gibt?
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
M JavaFX TreeView - TreeItem - SelectedItem AWT, Swing, JavaFX & SWT 7
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
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
JavaJakob22 ButtonGroups in verschiedenen Packages AWT, Swing, JavaFX & SWT 2
G 2D-Grafik Grafik in zwei verschiedenen Fenstern gleichzeitig zeichnen AWT, Swing, JavaFX & SWT 9
P Zwischen verschiedenen Panels wechseln AWT, Swing, JavaFX & SWT 3
B Java FX TableView Zeilen mit verschiedenen Typen AWT, Swing, JavaFX & SWT 15
R JTextArea mit verschiedenen Textfarben AWT, Swing, JavaFX & SWT 6
C Swing Aus verschiedenen Klassen zeichnen. AWT, Swing, JavaFX & SWT 2
HoloYoitsu Swing JButton in verschiedenen Winkeln drehen AWT, Swing, JavaFX & SWT 0
F Swing Drag and Drop in JTree aus verschiedenen Listen AWT, Swing, JavaFX & SWT 6
HaukeG Swing Drag & Drop in verschiedenen Varianten AWT, Swing, JavaFX & SWT 4
X JTable mit verschiedenen Objekten füllen AWT, Swing, JavaFX & SWT 14
F jTable mit verschiedenen Textfarben AWT, Swing, JavaFX & SWT 4
MQue JTable mit verschiedenen Models AWT, Swing, JavaFX & SWT 4
K Design von verschiedenen Rechnern AWT, Swing, JavaFX & SWT 13
dzim JFace TableViewer mit verschiedenen Inhalten AWT, Swing, JavaFX & SWT 4
A Verständnissproblem bei verschiedenen GUI's AWT, Swing, JavaFX & SWT 6
A Design Problem bei verschiedenen Oberflächen AWT, Swing, JavaFX & SWT 3
S [SWT] Toogle Button 2 verschiedenen images? AWT, Swing, JavaFX & SWT 6
S Starten von verschiedenen JFrames AWT, Swing, JavaFX & SWT 11
C Verschachtelung von JPanels mit verschiedenen LayoutManager AWT, Swing, JavaFX & SWT 4
B Auto. anpassen bei verschiedenen Aulösungen AWT, Swing, JavaFX & SWT 9
T Die Schrift in verschiedenen Farben blinken zu lassen AWT, Swing, JavaFX & SWT 2
D Textzeielen mit verschiedenen Textfarben in JList? AWT, Swing, JavaFX & SWT 6
P in JFrame zwischen verschiedenen JPanels wechseln AWT, Swing, JavaFX & SWT 7
N Zufallszahlen in verschiedenen Bereichen. AWT, Swing, JavaFX & SWT 4
B JList Zeilen in verschiedenen Farben markieren. AWT, Swing, JavaFX & SWT 3
K JTextArea mit verschiedenen Farben betreiben [Chat] AWT, Swing, JavaFX & SWT 3
G JTextArea.append() in verschiedenen Farben AWT, Swing, JavaFX & SWT 2
J Daten in verschiedenen JTables AWT, Swing, JavaFX & SWT 5
K JFrames in verschiedenen Fenstern AWT, Swing, JavaFX & SWT 2

Ähnliche Java Themen


Oben