JCheckBox datenstruktur

Kassel

Aktives Mitglied
Hi Community,

ich habe ein Programm geschrieben dass einen BinärenBaum darstellt und alle Blätter und Knoten sind JChckBoxen außer Wurzel. So jetzt möchte ich dass der Benutzer nur einen Weg von der Wurzel bis zum Blatt selektieren kann.

Nehmen wir an:
1. er selektiert einen Knoten , und dann noch ein Blatt
s1.jpg


2. dann selektiert er den Knoten darunter, dann soll automatisch der gegenüberliegende und seine Kinder Knoten und Blätter ... auf selected false gesetzt werden
s2.jpg


Wie kann ich so ein Handling bewerkstelligen mit einer Datenstruktur indem ich die CheckBoxen als Kinder und Eltern definiere ( wenn ja , wie geht dass ? )

oder mit einem speziellen Listener der so etwas abfangen kann

... ich habe es zur Zeit so gemacht dass ich alles per ActionListener gemacht habe , aber der code ist riesig und ich möchte es cleverer machen
 
Nach der Selektion eines Knotens merkst Du Dir zunächst einmal den Pfad bis zu diesem Knoten, anschliessend werden alle Knoten iterativ deselektiert, um dann anschliessend die Knoten im gemerkten Pfad wieder zu selektieren.

Du könntest auch JTree zur Darstellung deines Models verwenden, da ist so ein Verhalten schon implementiert.
 
hmm.. danke dass mit dem Jtree werde ich mir ansehen scheint die beste Lösung zu sein , doch kannst du mir sagen wie ich den Pfad zum Knoten wissen kann ?


EDIT:

Noch etwas ... wie soll dass überhaupt mit Jtree funktionieren ich brauche meine JCheckBoxen und die sind speziell positioniert ähnlich wie auf dem Bild , jedoch hat der Baum eine höhere Tiefe. Bei JTree wird es immer anders angezeigt, oder ist es unwichtig wie es aussieht ich soll nur meine JCheckBoxen in den Baum einpflanzen damit ich durch iterieren kann ?
 
Zuletzt bearbeitet:
Als kleiner Einwurf: Vermutlich (!) sollte die Datenstruktur für diesen Baum nichts mit JCheckboxen oder JTrees zu tun haben...
 
Hi Marco
was meinst du mit:

Als kleiner Einwurf: Vermutlich (!) sollte die Datenstruktur für diesen Baum nichts mit JCheckboxen oder JTrees zu tun haben...

???????? versteh dich nicht ....

also ich muss die Knoten selektieren können um am Ende darstellen zu können welchen Weg mein Programm ( Berechnung ) geht ...

kannst mir dein Einwand ein bisschen besser erklären ... danke nochmals
 
Hmja. Das Paradigma "Modell und View trennen" klingt schon fast zu plakativ. Man könnte suggestiv-philosophisch fragen: Willst du einen Baum aus CheckBoxen auf dem Bildschirm darstellen? Oder willst du den Aktivierungszustand einzelner Knoten in einem Binärbaum verwalten (und das zum Beispiel durch Anklicken von CheckBoxen auf dem Bildschirm)?

Irgendwas soll durch diesen Baum ja modelliert werden. Und meine Vermutung (!) war, das das unabhängig davon ist, ob man den Baum als JTree darstellt, oder als struktufrei hingemalte CheckBoxes, oder als Baum der mit irgendeinem Graphenvisualisierungstoolkit auf den Bildschirm gebracht wird....
 
Das mit dem JTree war jetzt nur ein Hinweis, sich dessen Verhalten und Implementierungen mal anzuschauen. Damit wird es vermutlich nicht - ohne extremen Aufwand - möglich sein, den Baum so wie in den Skizzen darzustellen.
So wie ich das verstanden habe, kann der Anwender einzelne Knoten de/selektieren und es soll immer der Weg von der Wurzel bis zum dem zu letzt selektierten Knoten dargestellt werden. Zur Darstellung von Graphen gibt es ja fertige Bibliotheken eventuell kann man da eine nutzen. Selbstzeichnen ist auch eine Möglichkeit.

Grundsätzlich brauchst Du ein Model, das die Knoten verwalten, die Knoten müssen dem Model sagen, wenn sie selektiert/deselektiert werden. Diese Model muss den relevanten "Pfad" (durch Iteration bis zur Wurzel) ermittlen und dann der View mitteilen, dass sich der Pfad geändert hat.

Falls das ganze nicht so wichtig, hier mal ein schnell abgewandeltes Bsp. aus meiner Demokiste, mit einem JTree:
Java:
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;

import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;

public class TreeDemoBinaer extends JFrame {
	private JTree tree;
	private DefaultMutableTreeNode root;
	private TreeSelectionModel selectionModel;
	private DefaultTreeModel model;
	
	public TreeDemoBinaer() {
		root = new DefaultMutableTreeNode("root");
		this.initializeNode(root, 0);
		this.model = new DefaultTreeModel(root);
		
		this.add(new JScrollPane(tree = new JTree(model)));
		this.selectionModel = tree.getSelectionModel();
		selectionModel.setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
		selectionModel.addTreeSelectionListener(new TreeSelectionListener() {
			public void valueChanged(TreeSelectionEvent e) {
				for (int i=0; i<root.getChildCount(); i++)
					resetStatus((DefaultMutableTreeNode)root.getChildAt(i));
				TreePath[] path = tree.getSelectionPaths();
				
				if (path==null)
					return;
				
				Object[] nodes = path[0].getPath();
				for (int i=1; i<nodes.length; i++) {
					DefaultMutableTreeNode node = (DefaultMutableTreeNode)nodes[i];
					CustomObject co = (CustomObject)node.getUserObject();
					co.setChecked(true);
				}
				tree.repaint();
			}
		});
		tree.setCellRenderer(new CustomTreeCellRenderer());
	}
	
	class CustomObject {
		String label;
		boolean checked = false;
		
		CustomObject(String label) {
			this.label = label;
		}
		
		public void setChecked(boolean b) {
			checked = b;
		}
		
		public boolean isChecked() {
			return checked;
		}

		public String getLabel() {
			return label;
		}
	}
	
	class CustomTreeCellRenderer extends DefaultTreeCellRenderer {
		public Component getTreeCellRendererComponent(JTree tree, Object value,
                boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {
    		super.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus);
    		DefaultMutableTreeNode node = (DefaultMutableTreeNode) value;
    		if (!node.equals(model.getRoot())) {
    			CustomObject co = (CustomObject)node.getUserObject();
    			this.setText(co.getLabel());
    			if (co.isChecked())
    				this.setIcon(checkIcon);
    			else
    				this.setIcon(emptyIcon);
    		}
    		return this;
    	}
	}
	
	int count = 0;
	private void initializeNode(DefaultMutableTreeNode node, int level) {
		if (level>3)
			return;
		for (int i=0; i<2; i++) {
			DefaultMutableTreeNode child = new DefaultMutableTreeNode(new CustomObject("AA" + level));
			this.initializeNode(child, level +1);
			node.add(child);
		}
	}
	
	private void resetStatus(DefaultMutableTreeNode node) {
		for(int i=0; i<node.getChildCount(); i++)
			this.resetStatus((DefaultMutableTreeNode)node.getChildAt(i));
		CustomObject co = (CustomObject)node.getUserObject();
		co.setChecked(false);
	}
	
	public static void main(String[] args) {
		JFrame frame = new TreeDemoBinaer();
		frame.setBounds(0, 0, 500, 300);
		frame.setLocationRelativeTo(null);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setVisible(true);
	}
	
	private Icon checkIcon = new ImageIcon() {
		public synchronized void paintIcon(Component c, Graphics g, int x, int y) {
			g.setColor(Color.RED);
			g.fillRect(0, 0, getIconWidth(), getIconHeight());
		}
		public int getIconWidth() {
			return 10;
		}
		public int getIconHeight() {
			return 10;
		}
	};
	private Icon emptyIcon = new ImageIcon() {
		public synchronized void paintIcon(Component c, Graphics g, int x, int y) {
			g.setColor(Color.RED);
			g.drawRect(0, 0, getIconWidth(), getIconHeight());
		}
		public int getIconWidth() {
			return 10;
		}
		public int getIconHeight() {
			return 10;
		}
	};
}
 
Hi Marco13 und Michael,

@Marko: ich verstehe jetzt was du mir sagen willst ... doch ich versuchte sie in einen tree zu stecken damit ich sie leichter handlen kann - halt durch iterieren usw.

@Michael ich werde mir dein beispiel angucken ich kann jetzt nichts dazu sagen da ich zur zeit nicht zu hause bin um es zu testen ... nochmals danke ich melde mich wenn ich dass beispiel durch gekaut habe

bis morgen ...
 
also dein Beispielprogramm ist ganz genau dass was ich brauche ... nur bei mir soll dass halt so aussehen wie in dem Bild am anfang also von links nach rechts und die checkboxen an vordefinierten stelle ... mein baum hat immer die gleiche tiefe er ändert sich also nicht ( könnte auch ein bild nehmen jedoch kann es sich ja später ändern des wegen soll es in swing umgesetzt werden )tiefe =4

wie kann ich jetzt dein beispielproogramm verwenden ... jedoch nicht deine gui zu nehmen sondern meine ( halt deine logik übernehmen ) ???

geht das überhaupt
 
Theoretisch könnte auf DefaultMutableTreeNode und DefaultTreeModel aufbauen und diese als/im Model verwenden. Das Model müsste dann nur noch den aktuell selektieren Knoten speichern können. Andererseits sind da viele Dinge dabei die man für Deine Anwendung nicht unbedingt benötigt und so ein Model, sollte relativ einfach und schnell selbst implementiert sein.
Letztendlich kommt es aber auch auf die verwendeten GUI Komponenten an. Sollen existierende Graphenbibliotheken verwendet werden, bringen diese - vermutlich - ihre eigenen Konzepte für solche Datenmodelle mit.

Grundsätzlich muss - aus meiner Sicht - das Model folgende Punkte erfüllen:
- die Knoten kennen Ihre Kind- und Ihren Elternknoten
- das Model muss die Knoten gesamthaft verwalten können (evtl. reicht es aus nur den Wurzelknoten zu kennen)
- es muss sich den aktiven/selektierten Knoten merken
- es muss den Pfad eines Knoten bis zur Wurzel ermitteln können
(- kann/soll der Baum dynamisch geändert werden, kommen dann noch ein paar weitere Methoden dazu)
 
Also ich habe gerade mein Problem gelöst ... un zwar habe ich einfach eine neue Klasse Box() erstellt die mir meine CheckBoxen handelt ... sie beinhaltet die eltern und die kinder und kann bei gebrauch den Baum durch gehen und die JCheckBoxen auf false oder true setzen ( setSelected ) ... wenn jemand noch einen Verbesserungsvorschlag hat, ruhig melden :

Java:
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package javaapplication7;

import java.util.ArrayList;
import javax.swing.JCheckBox;


public class Box extends JCheckBox{
    private ArrayList<Box> boxChildren=new ArrayList<Box>();
    private ArrayList<Box> boxParent=new ArrayList<Box>();

    public void add(Box chil) {
         this.getChildren().add(chil);
         this.addToParent(chil);
     }

    public void addToParent(Box chil){
         chil.getBoxParent().add(this);  
    }

    public void calculate(){
        this.setSelected(false);
        if(this.getChildren()!=null){
            for(Box box:this.getChildren())
            {
                box.setSelected(false);
                if(box.getChildren()!=null)
                for(Box boxes:box.getChildren()){
                    boxes.setSelected(false);
                }
            }
        }
    }

    public void setPathToRoot(){
        if(this.getParent()!=null){
            for(Box box:this.getBoxParent()){
                box.setSelected(true);
                for(Box parent:box.getBoxParent()){
                    parent.setSelected(true);
                }
            }
        }
    }

    /**
     * @return the children
     */
    public ArrayList<Box> getChildren() {
        return boxChildren;
    }

    /**
     * @return the boxParent
     */
    public ArrayList<Box> getBoxParent() {
        return boxParent;
    }


}

Hoffe es hilft jemandem ...🙂
 
Zuletzt bearbeitet:

Neue Themen


Zurück
Oben