Anzeige:
Ergebnis 1 bis 2 von 2

Thema: GTK - TreeModel in ComboBox

  1. #1
    Registrierter Benutzer Avatar von Rebell
    Registriert seit
    10.07.2002
    Ort
    Dresden
    Beiträge
    62

    GTK - TreeModel in ComboBox

    Hallo.

    Ich versuche seit Stunden, eine vernünftige Liste in eine GtkComboBox zu stecken, aber es vermag mir einfach nicht gelingen - trotz Beispielcode.

    Was ich habe: Eine einfache ComboBox mit Text.
    Was ich brauche: Ich benötige sozusagen mehrere Spalten, die ich dann nach belieben verstecken kann.
    Wozu ich das brauche: Einfache Einträge in der ComboBox nützen mir nichts, weil ich deren Index nicht bestimmen kann, weil dieser fortlaufend bei 0 anfängt. Möchte ich aber Einträge aus einer Datenbank mit ID und Text in die ComboBox einbauen, benötige ich mehr als einfache Texte.

    Schlau wie ich war, habe ich gelesen, dass es dafür GtkTreeModel gibt. Also hab ich gesucht und bin schnell fündig geworden. Das Beispiel funktioniert allerdings nur mit einem TreeView. Versuche ich das (gefüllte) TreeModel einer ComboBox zu übergeben, erscheint zwar der Tree, aber ohne Texte.

    Weiß jemand wie das genau funktioniert?

    Hier ist mein C-Code, den ich mir zusammengeschustert habe.
    Code:
    #include <gtk/gtk.h>
    
    static GtkTreeModel *
    create_and_fill_model (void)
    {
            GtkListStore *liststore;
            GtkTreeIter toplevel, child;
            
            liststore = gtk_list_store_new(2, G_TYPE_INT, G_TYPE_STRING);
            
            /* Append an empty top-level row to the tree store.
            *  Iter will point to the new row */
            gtk_list_store_append(liststore, &toplevel);
            
            /* Append another empty top-level row to the tree store.
            *  Iter will point to the new row */
            gtk_list_store_append(liststore, &toplevel);
            gtk_list_store_set (liststore, &toplevel,
                                    0, 1,
                                    1, "Hans",
                                    -1);
            /* Append a child to the row we just added.
            *  Child will point to the new row */
            gtk_list_store_append(liststore, &toplevel);
            gtk_list_store_set (liststore, &toplevel,
                                    0, 2,
                                    1, "Adam",
                                    -1);
    
            return GTK_TREE_MODEL(liststore);
    }
    
    static GtkWidget *
    create_view (void)
    {
      GtkTreeViewColumn   *col;
      GtkWidget           *view;
      GtkCellRenderer     *renderer;
    
      view = gtk_tree_view_new();
    
      /* --- Column #1 --- */
    
      col = gtk_tree_view_column_new();
      gtk_tree_view_column_set_title(col, "ID");
    
      /* pack tree view column into tree view */
      gtk_tree_view_append_column(GTK_TREE_VIEW(view), col);
    
      /* REnderer für erste Spalte */
      renderer = gtk_cell_renderer_text_new();
    
      /* pack cell renderer into tree view column */
      gtk_tree_view_column_pack_start(col, renderer, TRUE);
    
      /* connect 'text' property of the cell renderer to
       *  model column that contains the first name */
      gtk_tree_view_column_add_attribute(col, renderer, "text", 0);
    
    
    
    
      /* --- Column #2 --- */
    
      col = gtk_tree_view_column_new();
    
      gtk_tree_view_column_set_title(col, "Name");
    
      /* pack tree view column into tree view */
      gtk_tree_view_append_column(GTK_TREE_VIEW(view), col);
    
      gtk_tree_selection_set_mode(gtk_tree_view_get_selection(GTK_TREE_VIEW(view)),
                                  GTK_SELECTION_NONE);
    
      return view;
    }
    
    int
    main (int argc, char **argv)
    {
            GtkTreeModel *list;
            GtkWidget *window, *combo, *view, *vbox;
    
            gtk_init(&argc, &argv);
    
            window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
            g_signal_connect(window, "delete_event", gtk_main_quit, NULL);
    
            vbox = gtk_vbox_new (FALSE, 0);
            //gtk_widget_show (vbox);
            gtk_container_add (GTK_CONTAINER (window), vbox);
    
            combo = gtk_combo_box_new();
            list = create_and_fill_model();
            view = create_view();
    
            gtk_tree_view_set_model(GTK_TREE_VIEW(view), list);
            g_object_unref(list);
            gtk_combo_box_set_model(GTK_COMBO_BOX(combo), list);
    
            gtk_box_pack_start (GTK_BOX (vbox), combo, FALSE, FALSE, 0);
            gtk_box_pack_start (GTK_BOX (vbox), view, FALSE, FALSE, 0);
            gtk_widget_show_all(window);
    
    
            gtk_main();
    
            return 0;
    }
    Code:
    gcc combotree.c -o combotree `pkg-config gtk+-2.0 --cflags --libs`
    Erklärung:
    In der ComboBox, sowie im TreeView kommt ein Model aus 2 Spalten (ID, Name) zum Einsatz.
    Wobei das TreeModel in Wirklichkeit ein ListStore ist.
    Die ComboBox nimmt eigentlich NUR TreeModels an, wenn man es entsprechend castet auch List- bzw. TreeStores. In der GTK-Dokumentation steht, dass man ListStore und TreeStore in Verbindung von TreeView verwenden kann, aber mehr steht dazu nicht. Auch keine Erklärung wie man das in Elementen einbaut, die nur ein TreeModel unterstützen. Da ein TreeModel keine Daten halten kann, sondern nur deren Schnittstelle darstellt.

    Im TreeView unter der ComboBox fehlt für die 2te Spalte der Renderer und deshalb wird nur die ID angezeigt. Da in der ComboBox die Einträge zwar enthalten sind aber nicht angezeigt werden, vermute ich dass dort auch ein Renderer rein muss - aber wie?
    Geändert von Rebell (29-10-2005 um 14:24 Uhr)
    to be famous is so nice
    http://get-mike.de
    M:ke

  2. #2
    Registrierter Benutzer Avatar von Rebell
    Registriert seit
    10.07.2002
    Ort
    Dresden
    Beiträge
    62
    Ich habs hinbekommen:
    Code:
    #include <gtk/gtk.h>
    #include <string.h>
    
    static GtkTreeModel *create_and_fill_model (void)
    {
    	GtkTreeStore *liststore;
    	GtkTreeIter toplevel, child;
    	
    	// Erstelle Liste (2 Spalten, Typ Int, Typ String)
    	liststore = gtk_tree_store_new(2, G_TYPE_UINT, G_TYPE_STRING);
    
    	// Erster Eintrag (Wurzel)
    	gtk_tree_store_append(liststore, &toplevel, NULL);
    	gtk_tree_store_set (liststore, &toplevel,
    				0, 1,		// Spalte 1, Wert
    				1, "Hans",	// Spalte 2, Wert
    				-1);		// Ende
    
    	gtk_tree_store_append(liststore, &toplevel, NULL);
    	gtk_tree_store_set (liststore, &toplevel,
    				0, 2,
    				1, "Adam",
    				-1);
    
    	gtk_tree_store_append(liststore, &toplevel, NULL);
    	gtk_tree_store_set (liststore, &toplevel,
    				0, 3,
    				1, "Eva",
    				-1);
    	gtk_tree_store_append(liststore, &child, &toplevel);
    	gtk_tree_store_set (liststore, &child,
    				0, 4,
    				1, "Knut",
    				-1);
    	return GTK_TREE_MODEL(liststore);
    }
    
    static GtkWidget *create_view (void)
    {
    	GtkTreeViewColumn   *col;
    	GtkWidget           *view;
    	GtkCellRenderer     *renderer;
    
    	view = gtk_tree_view_new();
    
    	/* Erste Spalte */
    	col = gtk_tree_view_column_new();
    	
    	// Spaltenkopfbeschriftung
    	gtk_tree_view_column_set_title(col, "ID");
    
    	// An TreeView anhängen
    	gtk_tree_view_append_column(GTK_TREE_VIEW(view), col);
    
    	/* Renderer für erste Spalte */
    	renderer = gtk_cell_renderer_text_new();
    
    	// Packe Renderer in Spalte
    	gtk_tree_view_column_pack_start(col, renderer, TRUE);
    
    	// Setze Eigenschaft 'text' für Renderer
    	gtk_tree_view_column_add_attribute(col, renderer, "text", 0);
    
    
    	/* Spalte 2 */
    	col = gtk_tree_view_column_new();
    	gtk_tree_view_column_set_title(col, "Name");
    	gtk_tree_view_append_column(GTK_TREE_VIEW(view), col);
    
    	// -> Hier fehlt der Renderer	
    
    	// Auswahlmodus des TreeView
    	gtk_tree_selection_set_mode(gtk_tree_view_get_selection(GTK_TREE_VIEW(view)),
                                  GTK_SELECTION_NONE);
    	return view;
    }
    
    static GtkWidget *create_combobox(GtkTreeModel *model) {
    	GtkWidget *combo = gtk_combo_box_new_with_model(model);
    	GtkCellLayout   *layout;
    	GtkCellRenderer *renderer;
    
    	// Übernehme Zellenlayout
    	layout = GTK_CELL_LAYOUT (combo);
    	
    	// Neuer Textrenderer
    	renderer = gtk_cell_renderer_text_new();
    	
    	// Weise dem Layout den Textrenderer zu
    	gtk_cell_layout_pack_start (layout, renderer, FALSE);
    	
    	// Rendere Spalte 1 als Text, wies aussieht kann ComboBox nur eine Spalte darstellen
    	gtk_cell_layout_set_attributes  (layout, renderer, "text", 1, NULL);
    
    	return combo;
    }
    
    void
    combo_has_changed               (GtkComboBox     *combo,
                                            gpointer         user_data)
    {
    	GtkTreeIter selected;
    	GtkTreeModel *model;
    	GValue wert;
    	unsigned int id;
    	const gchar *text;
    	
    	// GValue deinitialisieren (mit 0 füllen)
    	memset(&wert, 0, sizeof(wert));
    
    	// Aktiven Eintrag holen
    	gtk_combo_box_get_active_iter(combo, &selected);
    	// TreeModel holen
    	model = gtk_combo_box_get_model (combo);
    	// Erste Spalte in GValue speichern
    	gtk_tree_model_get_value (model, &selected, 0, &wert);
    	// Hole uint ID
    	id = g_value_get_uint(&wert);
    	
    	// Vernichten
    	g_value_unset(&wert);
    
    	// Zweite Spalte in GValue speichern
    	gtk_tree_model_get_value (model, &selected, 1, &wert);
    	// Hole string Text
    	text = g_value_get_string(&wert);
    	g_print("ID: %d - Text: %s\n", id, text);
    	
    	// Nochmal vernichten
    	g_value_unset (&wert);
    }
    
    int
    main (int argc, char **argv)
    {
    	GtkTreeModel *model;
    	GtkWidget *window, *view, *vbox, *combo;
    
    	gtk_init(&argc, &argv);
    
    	window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    	g_signal_connect(window, "delete_event", gtk_main_quit, NULL);
    
    	vbox = gtk_vbox_new (FALSE, 0);
    	gtk_container_add (GTK_CONTAINER (window), vbox);
    
    	// Erstelle TreeModel (TreeStore)
    	model = create_and_fill_model();
    	
    	// Erstelle ComboBox mit TreeModel
            combo = create_combobox(model);
    	
    	// TreeView
    	view = create_view();
    	
    	// Weise Model dem TreeView zu
    	gtk_tree_view_set_model(GTK_TREE_VIEW(view), model);
    	g_object_unref(model);
    
    	// Aktiviere ersten Eintrag der ComboBox
    	gtk_combo_box_set_active(GTK_COMBO_BOX(combo), 0);
    
    	// Signal fürs Auswählen
    	g_signal_connect(combo, "changed", G_CALLBACK(combo_has_changed), NULL);
    
    	// In VBox packen
    	gtk_box_pack_start (GTK_BOX (vbox), combo, FALSE, FALSE, 0);
    	gtk_box_pack_start (GTK_BOX (vbox), view, FALSE, FALSE, 0);
    	gtk_widget_show_all(window);
    
    
    	gtk_main();
    
    	return 0;
    }
    Die einfache Listenversion, findet ihr auf Pronix (wo ich die Frage vorher gestellt hatte).
    http://www.pronix.de/comment/site-95...49/site-1.html
    Geändert von Rebell (30-10-2005 um 18:08 Uhr)
    to be famous is so nice
    http://get-mike.de
    M:ke

Lesezeichen

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •