QTreeView mit QTreeModel sollen dynamische Daten anzeigen

Alles zum Qt Framework für Java
Antworten
Forest
Beiträge: 26
Registriert: 22. Juni 2008 03:10

QTreeView mit QTreeModel sollen dynamische Daten anzeigen

Beitrag von Forest »

Vielleicht kann mir hier jemand helfen. Es sind gleich mal 3 Hauptfragen.

1.)
Ich will einen speziellen binären Blattsuchbaum mit Hilfe der QTreeView und QTreeModel Klassen visualisieren. Die Datenstruktur verändert sich ständig (dynamisch). Einfügungen, Entfernungen finden statt. Als weiteres kann es auch sein, dass mitten im Baum durch eine Rotation, ein Knoten einen anderen Teilbaum unter sich bekommt.

Die Signale von der Datenstruktur kommen bis jetzt zu eigenen Slots in die abgeleitete QTreeModel Klasse. Ich weiß somit was sich an welchem Objekt verändert hat. Aber wie teile ich das nun mit?

Wie ist die Kommunikation aus den Daten in Richtung QTreeModel, QTreeView vorgesehen?

Ich habe die QTreeModel Methode

Code: Alles auswählen

childrenInserted(QModelIndex parent, int first, int last) 
benutzt, was halbwegs funktioniert, jedoch ab und zu eine Exception bringt, in der unter anderem steht: "Expected 2, actual childCount() is 2"
Die

Code: Alles auswählen

childrenRemoved(QModelIndex parent, int first, int last)
Methode mag aber irgendwie bei mir gar nicht.
Und dann brauch ich ja immer noch was, wo ich einem Knoten sagen kann, du hast jetzt einen komplett neuen teilbaum unter dir. bau ihn auf. oder noch besser du hast jetzt den teilbaum der unter einem anderen knoten war unter dir.

2.)
ich hab 2 qt-jambi projekte in eclipse. in einem wird die javadoc von qt-jambi klassen angezeigt bei dem andren nicht. ich hab schon alle einstellungen der beiden projekte verglichen und find kein unterschied, wieso es bei einem angezeigt wird und beim anderen nicht.

3.)
wenn ich Pfade als String so wie in diesem Beispiel:

Code: Alles auswählen

pause.setIcon(new QIcon(new QPixmap("icons/pause.png")));
benutze, dann funktionierts. Wenn ich aber

Code: Alles auswählen

pause.setIcon(new QIcon(new QPixmap("classpath:icons/pause.png")));
mache, dann findet er das icon nicht. Woran liegt das?

Danke schon mal, falls mir jemand helfen kann.
ArneStocker
Beiträge: 300
Registriert: 3. November 2004 16:15
Wohnort: Berlin

Beitrag von ArneStocker »

3) wenn ich Pfade als String so wie in diesem Beispiel:
Code:
pause.setIcon(new QIcon(new QPixmap("icons/pause.png")));

benutze, dann funktionierts. Wenn ich aber
Code:
pause.setIcon(new QIcon(new QPixmap("classpath:icons/pause.png")));

mache, dann findet er das icon nicht. Woran liegt das?
ich fang mal damit an.

Du hast wahrscheinlich das 'pause.png' in einem Verzeichnis icons, welches sich relativ zu Deinem Projektpfad befindet. Das hat früher auch mit classpath funktioniert, jetzt aber nicht mehr. Besser ist es, eine Resource.jar Datei zu bauen, die du in den Classpath aufnimmst und die (im Unterverzeichnis icons) das Bildchen enthält.
2) ich hab 2 qt-jambi projekte in eclipse. in einem wird die javadoc von qt-jambi klassen angezeigt bei dem andren nicht. ich hab schon alle einstellungen der beiden projekte verglichen und find kein unterschied, wieso es bei einem angezeigt wird und beim anderen nicht.
In eclipse kannst Du den Sourcecode und Javadoc in den Properties (Java Build Path -> Register Libraries) für jedes jar einstellen / auswählen. Einfach den Unterpunkt JavaDoc location bearbeiten.

1) Wenn Du ein eigenes Model verwendest benötigst Du die Methoden m.E. gar nicht. Du musst nur die Struktur Deiner Daten ändern. Dein Model gibt dann für jedes ModelIndex die geänderten Daten zurück.

Vorsorglich könntest Du vor einer Änderung

Code: Alles auswählen

model.layoutAboutToBeChanged.emit();
... Änderung
model.layoudChanged.emit(); 
aufrufen.

Gruß Arne
Forest
Beiträge: 26
Registriert: 22. Juni 2008 03:10

Beitrag von Forest »

danke erstmal für die antwort.

zu 1)
ich hatte bisher, folgendes in meinem model gemacht (in der abgeleiteten TreeView klasse wurde nur der Konstruktor mit paar einstellungsmöglichkeiten der treeview modifiziert, sonst nix, keine methoden, nix überschrieben):

Code: Alles auswählen

public class RBRSMAB_Model extends QTreeModel {
	
	//Signal2<QModelIndex,QModelIndex> dataChange = new Signal2<QModelIndex,QModelIndex>();
	private RBRSMAB_TreeView treeView;
	public static boolean folgeDemAktuellenKnoten = true;
	
    public RBRSMAB_Model(QObject parent) {
        super(parent);       
        treeView = (RBRSMAB_TreeView)parent;
        //dataChange.connect(this,"dataChanged(QModelIndex,QModelIndex)");
        new RBRSMABNode(this);
    }
    
    /*
     * Dieser Slot ist mit jedem Knoten im Baum verbunden und wird aufgerufen wenn in einem Knoten der Text/Inhalt gändert worden ist.
     * Dadurch soll das Modell bzw. die View den Text des Knotens aktualisieren
     */
	public void aktualisiereKnotenText(RBRSMABNode n) {
		QModelIndex a = valueToIndex(n);
      treeView.update(a);
		if(folgeDemAktuellenKnoten) {		
		        treeView.setCurrentIndex(a);
		}
	}
	
	/*
	 * Dieser Slot wird aufgerufen, wenn beim Einfügen unter dem betroffenenKnoten 2 neue Blätter erzeugt werden
	 * Dies soll das Modell bzw. die View aktualisieren, um die neun Blätter anzuzeigen
	 */
    public synchronized void neueKinder(RBRSMABNode betroffenerKnoten,RBRSMABNode vater,RBRSMABNode linkerSohn,RBRSMABNode rechterSohn,String locks) {  	
		if(linkerSohn!=null&&rechterSohn!=null) {
			//layoutChanged.emit(); 
			QModelIndex a = valueToIndex(betroffenerKnoten);
			try {childrenInserted(a,0,1);}catch(IllegalArgumentException i){System.out.println("childrenInserted-mit Exception");/*treeView.expandAll();*/}
			treeView.expand(a);
		}
		
	}

    /**
     * Die Unsichtbare imaginäre Wurzel hat als einzigstes Kind die echte Wurzel des Baumes.
     * Alle inneren Knoten haben 2 Kinder.
     * Alle Blätter haben 0 Kinder.
     */
    @Override
    public int childCount(Object o) {
    	if(o==null)
    		return 1;
    	if(((RBRSMABNode) o).hasChildren())
    		return 2;
    	return 0;
    }

    /**
     * Gibt das Kind zurück, wobei in row 0 das linke und row 1 das rechte Kind sein soll
     * Will man das Kind der imaginären Wurzel "null" wissen, so gebe ich die tatsächliche Wurzel des Baumes zurück
     */
    @Override
    public Object child(Object o, int row) {
    	if(o==null)
    		return RBRSMABNode.rootNode;
    	if(o==null&&row!=0)
    		System.out.println("!!Da stimmt was nicht. Siehe child Methode in RBRSMAB_Model. Die imaginäre Wurzel darf nur 1 Kind haben");
    	if(row==0)
    		return ((RBRSMABNode) o).getLeftChild();
    	return ((RBRSMABNode) o).getRightChild();   	
    }

    /**
     * Gibt den String, der in einem RBRSMABNode steht zurück
     */
    @Override
    public String text(Object o) {
    	return ((RBRSMABNode) o).getText();
    }
}
An der stelle in der neueKinder Methode, wo

Code: Alles auswählen

layoutChanged.emit();
auskommentiert ist, habe ichs einkommentiert und den rest in der if anweisung auskommentiert. der baum startet bei mir immer nur mit der wurzel. dann sieht man nur die wurzel. und es kommen nie kinder hinzu in der view...

Übrigens gibts doch das Beispiel http://doc.trolltech.com/qtjambi-4.4/ht ... model.html
Da ist natürlich keine Beschreibung, aber die TreeModel.java ist im com/trolltech/examples Verzeichnis. Von der hab ich auch die Grundlegenden Methoden von oben abgeschaut. Bei dem TreeModel aus dem Beispiel, dass die Festplattenordner anzeigt, ist das selbe Problem, das es nicht dynamisch auf den Daten operiert. Wenn du z.B. die dir Methode wie folgt modifizierst:

Code: Alles auswählen

private QDir dir(Object value) {
            return value != null ? (QDir) value : new QDir("/home/user/Desktop");
        }
, wobei /home/user/Desktop irgend ein pfad auf deiner festplatte sein kann,
und dann das programm aufrufst und auf deinem desktop ne neue datei/ordner erstellst, dann wirst du merken, dass es niemals in dem tree erscheinen wird. wenn du was in nem unterverzeichnis was einfügst, das gerade in der TreeView sichtbar ist, dann wirst dus auch solange nicht zu gesicht bekommen bis du ein collapse und wieder expand per mausklick machst. Also wenn du eine idee hättest wie man dieses Beispiel dynamisch machen könnte, so dass ich dateien entfernen umbennen einfügen und sogar ordner mit ganzen unterordnern irgendwo auf der festplatte verschieben kann und die treeview zeigt mir sofort die aktualisierte festplattenstruktur an, dann würde ichs denke ich zu 100% auf mein problem mit der baum-datenstruktur übertragen können.
die einfügungen verschiebungen etc. sollen natürlich nicht per klicks in der treeview passieren, sondern ganz normal auf dem system. von der treeview verlang ich 0,0 interaktion. ich will nur, dass sie mir einfach ständig die aktuelle "festplatten"- bzw. baum- struktur anzeigt.
da sind vielleicht nur paar zeilen code verlangt, vielleicht ein slot-aufruf oder ein emit. ich hab aber keine ahnung welchen slot oder signal aufgerufen werden soll und mir schon die finger wund probiert. lediglich oben das einfügen funktioniert, nur dass manchmal nach paar 100 einfügungen ne exception kommt.

zu 2) danke, irgendwie war ich da natürlich, hab aber die jars nicht aufgeklappt und damit diese einstellungsmöglichkeiten nicht gesehen (und vergessen das die da waren) :)

stellst du dann das .../doc/html verzeichnis da ein, oder die internetseite? besser lokal, oder? ist dann schneller und funzt auch im notfall ohne inet

bei Native library location oder Source Atachment, kann man da eigentlich für Qt-Jambi 4.4 auch was eingeben??? Kann man da das Qt-Jambi Source Package (in linux qtjambi-src-gpl-4.4.0_01.zip) angeben, oder bringt das nix? oder es entpacken und angeben? paar .java dateien hab ich zumindest drin gesehen...
Bindest du das Source Package auch als .jar ein, oder macht das dann kein sinn mehr, wenn man die vorkompilierte (in Linux qtjambi-linux32-gcc-4.4.0_01.jar) und die plattform unabhängige (qtjambi-4.4.0_01) eingebunden hat?

zu 3) ja, du hast recht, wenn ich es in ne .jar packe und dann einbinde, dann gehts mit classpath:
Ich will aber vielleicht später noch icons hinzufügen oder welche entfernen, was doch irgendwie ja dann nicht mehr geht (habs probiert). Und wenn ich später mal das zum Ausführen weitergeben will, hätte ich schon gerne, dass jemand auch drauf zugriff hat. Weil, ich habe einige Textdateien, die das Programm zu Beginn einliest, wenn der Benutzer es mit anderen laufen lassen will, dann könnte er die einfach ersetzen, durch andere gleichnamige. Da es dann aber in einer .jar ist geht das wohl schlecht. Also muss ichs doch wieder so ohne classpath: machen und dann später die ordner mit den Textdateien dazulegen?

4) die QTreeModel klasse gibts doch in Qt gar nicht, aber ich find die QTreeModel.java nicht, dies doch eigentlich dann geben müsste. Find sie auch nicht im Source Package von Qt Jambi ...
Wäre nämlich schon gut, wenn ich reinschauen könnte wie das implementiert ist, dann kann man ggf. besser überschreiben, oda verstehen, oder nachmachen.

ist halt nicht einfach sachen zu programmieren ohne wie sonst üblich in java einfach in den quellcode zu schauen.
Antworten