Unbekannte Methode add bei Klasse die JTree erweitert

Carcharoth

Bekanntes Mitglied
Hallo

Ich befasse mich mit einer Klasse die ich als Erweiteung von JTree baue. Ich habe meinen Code auf den Kern des Problems bereinigt (siehe unten). Dabei stosse ich auf die Fehlermeldung, wonach die Methode add nicht für den Knoten-Typ DefaultMutableTreeNode existiert.

Ich stehe auf dem Schlauch wieso das so ist, und vor allem wie ich das lösen kann.
Muss ich meine Klasse Baum von einer weiteren Klasse erben lassen ?

Danke und Gruss

Java:
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeNode;

public class Baum extends JTree {

    public Baum() {
        super();
        DefaultMutableTreeNode wurzel= new DefaultMutableTreeNode("Wurzel");
        add(wurzel);
    }   
}
 
Beste Antwort
Ich empfehle erstmal das Lesen von: https://docs.oracle.com/javase/tutorial/uiswing/components/tree.html
Wenn du mit einem Node als Wurzel arbeitest, dann musst du den JTree bereits mit diesem Node in seinem Konstruktor initialisieren.
Einen Node kann man nicht mehr im Nachhinein zum JTree hinzufügen.
Also z.B. so:
Java:
public class Baum extends JTree {
    private final DefaultMutableTreeNode wurzel = new DefaultMutableTreeNode("Wurzel");
    public Baum() {
        super(wurzel);
    }
}
Oder du verwendest ein TreeModel, das kannst du auch im Nachhinein per setModel() setzen.
Ich empfehle erstmal das Lesen von: https://docs.oracle.com/javase/tutorial/uiswing/components/tree.html
Wenn du mit einem Node als Wurzel arbeitest, dann musst du den JTree bereits mit diesem Node in seinem Konstruktor initialisieren.
Einen Node kann man nicht mehr im Nachhinein zum JTree hinzufügen.
Also z.B. so:
Java:
public class Baum extends JTree {
    private final DefaultMutableTreeNode wurzel = new DefaultMutableTreeNode("Wurzel");
    public Baum() {
        super(wurzel);
    }
}
Oder du verwendest ein TreeModel, das kannst du auch im Nachhinein per setModel() setzen.
 
Beste Antwort
Ich befasse mich mit einer Klasse die ich als Erweiteung von JTree baue. Ich habe meinen Code auf den Kern des Problems bereinigt (siehe unten). Dabei stosse ich auf die Fehlermeldung, wonach die Methode add nicht für den Knoten-Typ DefaultMutableTreeNode existiert.
Weil Du JTree nicht verstanden hast.
Der Baum wird über den Startknoten gesteuert nicht mittels JTree.

Java:
    DefaultMutableTreeNode root = new DefaultMutableTreeNode("Root");
        JTree tree = new JTree(root) ;       
        String []names = {"Paul","Peter","Hans"};
        for( String s : names )
            root.add(new DefaultMutableTreeNode( s ));
 
Ich empfehle erstmal das Lesen von: https://docs.oracle.com/javase/tutorial/uiswing/components/tree.html
Wenn du mit einem Node als Wurzel arbeitest, dann musst du den JTree bereits mit diesem Node in seinem Konstruktor initialisieren.
Einen Node kann man nicht mehr im Nachhinein zum JTree hinzufügen.
Also z.B. so:
Java:
public class Baum extends JTree {
    private final DefaultMutableTreeNode wurzel = new DefaultMutableTreeNode("Wurzel");
    public Baum() {
        super(wurzel);
    }
}
Oder du verwendest ein TreeModel, das kannst du auch im Nachhinein per setModel() setzen.

Danke erstmal für den Tipp. Ich werde auf die Doku lesen.

Das mit der Wurzel im Konstruktor leuchtet mir ein. Ich war schon auf das Problem gestossen, dass ich nichts vom dem Aufruf des Konstruktors der Superklasse haben darf. Daher den Trick mit der Wurzel als Klassenvariable. Müsste diese nicht eher static sein ?
 
Ok.
Aber funktioniert bei mir mit "final" nicht. Dann heisst es "Cannot refer to an instance field wurzel while explicitly invoking an construktor."
Mit "static" läuft es einwandfrei.
 
Dann hast Du irgend einen dubiosen Code, bei dem Du auf eine Instanzvariable zugreifst, ee diese initialisiert werden konnte.
Und das static ist da dann vermutlich auch keine Lösung, denn damit sorgst Du nur dazu, dass die Variable halt den initialen "Null-Wert" hat. Aber dennoch wirst Du Dir sehr wahrscheinlich etwas anderes gedacht haben, als der Code effektiv machen wird.

Daher wie @temi schrieb: Zeig Deinen Code, erläutere ggf noch, was Du genau machen willst und wo Du den Fehler bekommst und dann können wir Dir weiter helfen.
 
Mein Code hat gar nicht viel mehr.... hier der ganze Code.
Fakt ist, dass es mit static läuft, mit final nicht und ganz ohne static und final auch nicht.
Wieso verstehe ich (noch) nicht.

Code:
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;

public class Baum extends JTree {
    
    private static DefaultMutableTreeNode wurzel = new DefaultMutableTreeNode("Wurzel");
    
    public Baum() {
        super(wurzel);
    }   
}


Code:
public class Test {

    public static void main(String[] args) {
        Baum baum = new Baum();
    }
}
 
Der erste Hinweis hier wäre FCoI: Favor Composotion over Inheritance.

Du willst ja nicht wirklich die Verhaltensweise von JTree verändern sondern lediglich ein JTree bei deinem Baum nutzen.

Ansonsten wäre so ein Konstrukt denkbar:
Java:
public class Baum extends JTree {

    private final DefaultMutableTreeNode wurzel;

    public Baum(DefaultMutableTreeNode wurzel) {
        super(wurzel);
        this.wurzel = wurzel;
    }

    public Baum() {
        this(new DefaultMutableTreeNode("Wurzel"));
    }
}

Aber ich würde da eher (auf Grund des ersten Punktes FCoI) etwas nehmen wie:
Java:
public class Baum {

    private final DefaultMutableTreeNode wurzel;
    private final JTree tree;
    
    public Baum() {
        wurzel = new DefaultMutableTreeNode("Wurzel");
        tree = new JTree(wurzel);
    }
}
 
Danke !
Ich glaube ich verstehe ansatzweise was du meinst. Ursprünglich war ich sogar auf die zweite Lösung gekommen aber dachte, es wäre wohl ein Versuch wert die Klasse Tree von der Klasse JTree erben zu lassen.
Offensichtlich muss man da mit diesem static etwas vorsichtig sein...
 
Das mit der Wurzel im Konstruktor leuchtet mir ein. Ich war schon auf das Problem gestossen, dass ich nichts vom dem Aufruf des Konstruktors der Superklasse haben darf. Daher den Trick mit der Wurzel als Klassenvariable. Müsste diese nicht eher static sein ?
Also static auf keinen Fall. Besser als die Wurzel zu nehmen ist ein Model. Hier ein Beispiel.
1675000170202.png
Java:
import javax.swing.JFrame;

public class StartTree {
    public static void main(String[] args) {
        JFrame frame = new JFrame("Tree");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(new TreePanel(400, 400));
        frame.pack();
        frame.setVisible(true);
    }
}
Java:
import java.awt.Dimension;
import javax.swing.JButton;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;

@SuppressWarnings("serial")
public class TreePanel extends JPanel {
    private DefaultTreeModel model = new DefaultTreeModel(new DefaultMutableTreeNode("root"));
    private JTree tree = new JTree(model);

    public TreePanel(int width, int height) {
        setPreferredSize(new Dimension(width, height));
        JScrollPane scroll = new JScrollPane(tree);
        JButton insert = new JButton("add");
        JButton remove = new JButton("remove");
        scroll.setPreferredSize(new Dimension(width, 7*height / 8));
        insert.addActionListener(e -> {
            String input = JOptionPane.showInputDialog(this, "Knoten eingeben!");
            if (input != null) {
                DefaultMutableTreeNode selectedValue = getSelectedValue();
                if (selectedValue == null)
                    selectedValue = (DefaultMutableTreeNode) model.getRoot();
                DefaultMutableTreeNode value = new DefaultMutableTreeNode(input);
                model.insertNodeInto(value, selectedValue, 0);
                tree.setSelectionPath(new TreePath(model.getPathToRoot(value)));
            }
        });
        remove.addActionListener(e -> {
            DefaultMutableTreeNode selectedValue = getSelectedValue();
            if (selectedValue != null)
                model.removeNodeFromParent(selectedValue);
        });
        add(scroll);
        add(insert);
        add(remove);
    }

    private DefaultMutableTreeNode getSelectedValue() {
        return (DefaultMutableTreeNode) tree.getLastSelectedPathComponent();
    }
}
 

Anhänge

Natürlich, darum lernt man ja die Sprache - z.B. unter Zuhilfenahme dieses Forums. Wenn ich alles schon wüsste, wäre ich nicht hier.
Auf Static bin ich nicht einfach so gekommen, sondern weil Eclipse mir das als Lösungsweg vorgeschlagen hat.
Nun weiss ich es aber besser.
 

Neue Themen


Zurück
Oben