CellRendererCombo - Einträge erstellen

Programmierung für GNOME und GTK+, GUI-Erstellung mit Glade.
Antworten
Barabbas
User
Beiträge: 349
Registriert: Dienstag 4. März 2008, 14:47

Hallo,

ich möchte in einem TreeView eine Combobox einfügen. Am liebsten wäre mir eigentlich sogar das normale GTK-ComboBox-Widget, aber das scheint nicht ohne Aufwand zu gehen. Also habe ich mir den CellRendererCombo mal näher angesehen.

Dazu habe ich hier eigentlich ein schönes Beispiel gefunden. Problem dabei: In dem Beispiel wird beim Erstellen des Renderers und der dazugehörigen Column auch einfach direkt das ListStore für den CellRendererCombo erstellt und befüllt. Es gibt aber keinen Hinweis darauf, wie ich etwa zur Laufzeit eine neue Zeile hinzufüge und dem ComboRenderer dabei gleich beispielsweise 10 Einträge für die Combobox übergebe.

Ich habe mal einen Ausschnitt meines Codes hochgeladen: http://www.python-forum.de/pastebin.php ... ght=python

Die Methode __add_columns() erstellt einfach die Columns und die dazugehörigen Renderer. Das TreeView-Model wird mit der Methode __create_model() erstellt. Der Knackpunkt ist nun die Methode add_entry(): Der Parameter "languages" enthält eine Liste von Zeichenketten, die jeweils einen Eintrag in der ComboBox darstellen sollen. So wie ich das aber bisher gelöst habe, wird lediglich ein Eintrag in der ComboBox erstellt, der dann ["erster Eintrag", "zweiter Eintrag, ...] heißt - die Liste wird also nicht aufgelöst sondern als String übernommen.

Nun die Frage: Wie muss ich die Methode add_entry() erweitern, um in der neuen Zeile den CellRendererCombo korrekt zu befüllen. Eigentlich müsste ja mit jeder neuen Zeile auch ein neues Model für doe ComboBox erstellt werden - wie komme ich daran?

Ich hoffe, das Problem ist einigermaßen verständlich.

Besten Dank!

brb
BlackJack

@Barabbas: Schau Dir das Beispiel noch mal an: Das `ListStore` für den `TreeView` hat an der Spalte wo die Combo-Zelle angezeigt werden soll den Typ `gobject.TYPE_OBJECT`. Das fehlt bei Dir irgendwie. Und wenn bei Dir nicht alle Zeilen die selbe Auswahl in der Combo-Zelle haben sollen, dann musst Du auch ein `CellRendererCombo` mit dazugehörigem `ListStore` *pro* Zeile, die Du hinzufügst, erzeugen. Würde ich jetzt mal so behaupten.
Barabbas
User
Beiträge: 349
Registriert: Dienstag 4. März 2008, 14:47

Hallo Black Jack,

danke für den Hinweis. Zumindest der zweite Teil stimmt aber (glaube ich) nicht:
dann musst Du auch ein `CellRendererCombo` mit dazugehörigem `ListStore` *pro* Zeile, die Du hinzufügst, erzeugen. Würde ich jetzt mal so behaupten
Alle anderen CellRenderer muss man ja auch nur pro Spalte einmal erzeugen - den Rest macht gtk für mich. Ich muss aber ehrlich sagen, dass ich da auch keinen besonderen Durchblick habe.

Der erste Hinweis bzgl. des TYPE_OBJECTS hat mir schonmal ein wenig weitergeholfen - ich denke, dass das zum Ziel führen könnte.

Wie gesagt: Danke dass du dir die Mühe gemacht hast, einen Blick in den Code zu werfen.

Schönen Gruß,

brb
Benutzeravatar
Trundle
User
Beiträge: 591
Registriert: Dienstag 3. Juli 2007, 16:45

Ich würde fast behaupten, man kann nur ein Model nehmen, das sich alle Zeilen teilen. Allerdings ist es auch nicht soo schwer, sich einfach ein eigenes `CellRendererCombo` zu bauen, das das tut, was man will: Link.


Wow, ganz tolles Pastebin: "Die Erweiterung py ist nicht erlaubt. Du hast kein Snippet eingefügt oder keine gültige Datei zum Upload ausgewählt."
"Der Dumme erwartet viel. Der Denkende sagt wenig." ("Herr Keuner" -- Bertolt Brecht)
Barabbas
User
Beiträge: 349
Registriert: Dienstag 4. März 2008, 14:47

Hi Trundle
Ich würde fast behaupten, man kann nur ein Model nehmen, das sich alle Zeilen teilen
Ich verstehe jetzt nicht ganz, was du damit ausdrücken möchtest. Bezieht sich das noch auf den Kommentar von BlackJack?
Allerdings ist es auch nicht soo schwer, sich einfach ein eigenes `CellRendererCombo` zu bauen, das das tut, was man will: Link.
Ja, sowas in der Art habe ich auch schon gefunden. Aber eigentlich handelt es sich dabei nur um exakt den gleichen Code, den ich ins Pastebin gestellt habe, mit dem Unterschied, dass ein eigenes CellRendererCombo erstellt wurde.

Mir geht es um die Frage, wie ich einer ComboBox in einer neu erstellten Zeile zur *Laufzeit* neue Einträge verpassen kann. In deinem Beispiel werden die Einträge ja auch bereits mit dem Erstellen des CellRendererCombos festgelegt.
Hier nochmal der aktuelle Code, der eigentlich die Übertragung dessen ist, was mein und dein Beispiel machen. Es funktioniert aber nicht, die ComboBox bleibt leer, obwohl ich mittlerweile für den CellRendererCombo im Liststore TYPE_OBJECT gesetzt habe. Zur Veranschaulichung der relevante Ausschnitt aus meinem aktuellen Code:

Code: Alles auswählen

    def add_entry(self, title, duration, aspect, languages, subpicture, profile):
        model = self.get_model()

        m = gtk.ListStore(gobject.TYPE_STRING)
        for lang in languages:
            m.append([lang])
                    
        iter = model.append()
        model.set(iter, 
            COLUMN_CHECK, False, 
            COLUMN_TITLE, title,
            COLUMN_DURATION, duration,
            COLUMN_ASPECT, aspect,
            COLUMN_LANGUAGE, m, 
            COLUMN_SUBTITLE, subpicture,
            COLUMN_PROFILE, profile)   
Ich erstelle also eine neue Zeile (model.append()) und setze dann den Inhalt der Zellen (model.set). Die COLUMN_LANGUAGE ist der CellRendererCombo und bekommt einen ListStore mit den gewünschten Strings übergeben.

Schönen Gruß,

brb
Benutzeravatar
Trundle
User
Beiträge: 591
Registriert: Dienstag 3. Juli 2007, 16:45

Ich muss sagen, ich verstehe nicht, was du willst. Zur Laufzeit neue Einträge verpassen? Einfach an das Model eine neue Zeile hinzufügen, fertig.

Das scheint es aber nicht zu sein, vielmehr willst du wohl, dass für jede Zeile in deinem TreeView der Combo-Renderer unterschiedliche Einträge hat. Und die Einträge möchtest du eben aus dem Model vom TreeView haben. Das geht eben mit einem `CellRendererCombo` nicht, der hat nur genau *ein* Model, das er für *alle* Zeilen benutzt. Mein Renderer hingegen holt sich das Model für die Combo aus dem Model vom TreeView, was mir das zu scheinen seint, was du erreichen willst. Wenn du also wirklich denkst, dass dein Code und mein Code dasselbe tun, solltest du vielleicht mein Beispiel noch einmal in Ruhe anschauen.
"Der Dumme erwartet viel. Der Denkende sagt wenig." ("Herr Keuner" -- Bertolt Brecht)
Barabbas
User
Beiträge: 349
Registriert: Dienstag 4. März 2008, 14:47

Ich muss ehrlich gestehen, dass ich dich auch nicht ganz verstehe - was aber durchaus an mir liegen kann: So wie ich ein TreeView verstehe, definiere ich doch bestimmte Spalten und sage: In Spalte 1 ist eine Checkbox, Spalte 2 ist editierbar und Spalte 3 enthält eben eine ComboBox. Und jede Zelle einer Spalte ist völlig eigenständig: Wenn ich in Spalte(S) 1, Zeile(Z) 1 eine Checkbox klicke, ist deswegen ja auch noch lange nicht die Checkbox in S1, Z2 angeklickt. Und der Inhalt der editierbaren Zelle S2,Z1 ist völlig unabhängig von der Zelle in S2,Z2.

So wie du das schilderst ("Das geht eben mit einem `CellRendererCombo` nicht, der hat nur genau *ein* Model, das er für *alle* Zeilen benutzt") hört sich das aber so an, als ob alle Zeilen im TreeView den selben Inhalt haben müssten.

Hier mal ganz doof eine alternative Implementierung, die ich mit Widgets gemacht habe:
http://bilder.xn--ngel-5qa.de/bilder/12 ... nshot1.png

Genau sowas wollte ich halt als TreeView.

So, danke für deine Geduld. Wie man auf dem Bild sieht, habe ich vorerst ein Workarround gefunden, weswegen ich hier auch nicht länger den Begriffstutzigen spielen will ;). Aber vielleicht verstehst du jetzt ja besser, was ich will.
Benutzeravatar
Trundle
User
Beiträge: 591
Registriert: Dienstag 3. Juli 2007, 16:45

Dir ist schon klar, dass das Model, das der `CellRendererCombo` für seine Einträge beim Editieren benutzt, völlig unabhängig von dem Model ist, das der TreeView benutzt?
"Der Dumme erwartet viel. Der Denkende sagt wenig." ("Herr Keuner" -- Bertolt Brecht)
Barabbas
User
Beiträge: 349
Registriert: Dienstag 4. März 2008, 14:47

Ja? Sag mal: Hast du dir eigentlich mal *meinen* Code angesehen? Da erstelle ich doch bei jedem add_entry() (also für jede neue Zeile) ein neues Model für den CellRendererCombo.

Ich finde es auch nicht so prickelnd, dass ich hier versuche, mich halbwegs verständlich zu machen und du mich mit solchen Fragen für dumm verkaufst. Falls dir ein Fehler in meinem Code aufgefallen sein sollte, wäre ich sehr dankbar, wenn du darauf hinweisen würdest, statt mir Fragen zu stellen, die mich nicht weiter bringen. Wenn du verstanden hast, was ich will, solltest du das Problem / meinen Denkfehler doch auf den Punkt bringen können. So wie ich das überblicke, teilen sich ja CellRendererCombo und TreeView in meinem Code kein Modell, weshalb sich deine Frage erübrigt?
Benutzeravatar
Trundle
User
Beiträge: 591
Registriert: Dienstag 3. Juli 2007, 16:45

Okay, ich bin hier raus. Entweder ich verstehe wirklich nicht, was du willst, oder ich verstehe nicht, was an meinem Code nicht so ist, wie du es haben willst. Ich jedenfalls hatte niemals die Intention, dich zu provozieren. Stattdessen habe ich mich bemüht, ein kompaktes aber dennoch komplettes und auch *ausführbares* Beispiel zum Experimentieren zu erstellen, das klar und verständlich ist. Offensichtlich ist es mir nicht gelungen. Aber mir dann zu unterstellen, ich habe den ursprünglichen Code der Frage nicht einmal angesehen, geht zumindest für mich dann doch etwas zu weit.
"Der Dumme erwartet viel. Der Denkende sagt wenig." ("Herr Keuner" -- Bertolt Brecht)
grindhold
User
Beiträge: 3
Registriert: Dienstag 23. November 2010, 18:49

Ich poste einfach mal hier, weil ich auch noch ne frage zu CellRenderern und Models habe. Falls das nen eigenen Thread braucht, liebe Mods, scheut euch nicht ihn zu moven :)

Meine Frage ist recht simpel: Kann ich aus der render() eines beliebigen cellrenderers zugriff auf das model des trees bekommen? Problem: Zwei spalten. Die eine enthaelt eine ObjektID, die andere eine TypID. Nur wenn die TypID einen bestimmten wert hat, soll die ObjektID gerendert werden. Dazu braeuchte ich ja (wenn ich das richtig erkenne) in der renderfunktion den iter, den der cellrenderer Aktuell behandelt und das Model.
Wie komme ich an den Iter?

Gruesse, Grindhold
Antworten