Anzeige:
Ergebnis 1 bis 11 von 11

Thema: Gtk Callback mehrere Parameter übergeben

  1. #1
    Registrierter Benutzer
    Registriert seit
    19.10.2005
    Beiträge
    5

    Gtk Callback mehrere Parameter übergeben

    Also ich bin ziemlich neu in C eingestiegen und habe direkt mit Gtk Programmierung angefangen. Das hat bis jetzt auch ziemlich gut geklappt. Allerdings gibt es da ein Problem, das ich nicht so ganz aus der Welt schaffen kann.

    Wie verbinde ich ein Signal eines Buttons mit einer Callback Funktion und übergebe der Funktion dabei mehrere Parameter? Ich finde dazu nichts in den Tutorials etc.

    Wäre für Hilfe sehr Dankbar!

  2. #2
    Registrierter Benutzer
    Registriert seit
    17.04.2002
    Beiträge
    185
    Hallo,
    du hast bei den signals ja immer noch den Parameter: gpointer data
    Darüber kannst du beliebeige Daten schicken. Allerdings kannst du nicht mehrere data Parameter haben, ich denke mal das ist das was du meinst. Wenn du mehrere Daten hast, dann mußt du dir halt was einfallen lassen. Wenn die Daten alle vom gleichen Typ sind, dann könntest du sie in einem array mitschicken, eine glist verwenden oder einen struct erstellen der deine Daten hält um mal ein paar Möglichkeiten zu nennen.

    For a world where freedom and knowledge survives the compiler! (https://www.fsfe.org)

    If art interprets our dreams, the computer executes them in the guise of programs!

  3. #3
    Registrierter Benutzer
    Registriert seit
    19.10.2005
    Beiträge
    5
    Gut Vielen Dank für die Antwort!
    Dachte es gäbe vielleicht eine andere Möglichkeit. Dann werde ichs wohl als array machen

  4. #4
    Registrierter Benutzer
    Registriert seit
    19.10.2005
    Beiträge
    5
    Hmm irgendwie klappt das Ganze aber noch nicht so, wie ich das gern hätte. Die wichtige Zeile sieht bei mir so aus:

    Code:
    buttonArrayProfile[0] = buttonImages; //erster Button Widget
    buttonArrayProfile[1] = buttonChat; //zweiter Button Widget
    g_signal_connect(G_OBJECT(buttonProfile), "pressed", G_CALLBACK(changeMenuActivity), (gpointer) buttonArrayProfile);
    So lässt sich das auch kompilieren allerdings meint Gtk beim klick auf den Button folgenden Fehler ausgeben zumüssen:

    Code:
    (48tool:6704): GLib-GObject-WARNING **: invalid uninstantiatable type `(null)' in cast to `GtkToggleButton'
    
    (48tool:6704): Gtk-CRITICAL **: gtk_toggle_button_set_active: assertion `GTK_IS_TOGGLE_BUTTON (toggle_button)' failed

  5. #5
    Registrierter Benutzer
    Registriert seit
    05.09.2002
    Ort
    Neuhausen
    Beiträge
    320
    Ich arbeiten üblicherweise mit einem Applikations-Objekt (GObject) bzw. struct in einfacheren Fällen. Dazu verwende ich während der Entwicklungszeit eine Magic-Number, die mir bei der Fehlersuche schon sehr oft geholfen hat. Hier ein Beispiel:
    Code:
    #define MAGIC 0x39a7b26f /* zufällig! */
    
    typedef struct {
        /* was auch immer gebraucht wird */
        gint magic;
    } Appdata;
    
    void on_button_clicked(GtkWidget *button, gpointer user_data) {
        Appdata *data = (Appdata*)user_data;
        g_assert(data->magic == MAGIC);
        /* hier weiter auf Felder in data zugreifen */
    }
    
    int main() {
        Appdata data;
        data.magic = MAGIC;
        /* weiter initialisierungen von data */
        gtk_init(argc, argv);
        /* widgets erstellen, signale verbinden etc. */
        g_signal_connect(G_OBJECT(button), "clicked",
                         G_CALLBACK(on_button_clicked), &data);
        gtk_main()
        /* cleanup */
        return 0;
    }
    Wenn Appdata ein GObject ist, kannst du dir die Magic-number sparen, da wird sowieso bei jedem cast der Type überprüft.

    Eine weitere Möglichkeit für die Übergabe von Daten ist g_object_set_data(). z.B. könnte man im Beispiel oben direkt Daten an button hängen:
    Code:
    g_object_set_data(G_OBJECT(button), "mydata", mydata);
    Diese können dann in der Callback-Funktion wieder ausgelesen werden:
    Code:
    void on_button_clicked(GtkWidget *button, gpointer user_data) {
        MyData *mydata = g_object_get_data(G_OBJECT(button), "mydata");
    }
    Gruss, Andy

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

    Ich weiß was du willst, und zwar in einer Callback-Funktion auf alle verfügbaren Elemente des Fenster zugreifen können.

    Ich stand vor kurzem auch vor dem Problem, und dachte mir dass ich dazu die Callback-Funktionen mit entsprechenden Parametern ausstatten müsste, oder die Elemente global initialisiere. Da das beides völliger Schwachsinn ist und ich sowieso Glade verwende (wo das gar nicht funktioniert) habe ich mal in der Glade-Dokumentation gegoogelt und lookup_widget() gefunden. Diese Funktion gibt dir einen Zeiger auf ein Element deiner Wahl zurück, ähnlich der getElementById() in Javascript.

    Code:
    void
    on_button1_released                    (GtkButton       *button,
                                            gpointer         user_data)
    {
    
            GtkWidget *eingabefeld = lookup_widget(GTK_WIDGET(button), "entry1");
            char *text = (char*)gtk_entry_get_text (GTK_ENTRY(eingabefeld));
            g_print("g_print: %s\n", text);
    }
    lookup_widget durchsucht rekursiv den gesamten Elemente-Baum und gibt bei Fund den Zeiger darauf zurück.

    Hinweis: Diese Funktion befindet sich in "support.c" und wird nur generiert, wenn das Häkchen bei "Unterstützende Funktionen erzeugen" gesetzt ist.
    to be famous is so nice
    http://get-mike.de
    M:ke

  7. #7
    Registrierter Benutzer
    Registriert seit
    05.09.2002
    Ort
    Neuhausen
    Beiträge
    320
    Wenn nicht die (veraltete) Code-Generierung von Glade verwendet wird, bietet das libglade API die Funktion glade_xml_get_widget().

    Alternativ kann auch eine Widget-Lookup-Funktion verwendet werden, die unabhängig von Glade arbeitet und nur die Introspection-Funktionen von Gtk verwendet. Ich verwende dafür eine Funktion basierend auf Gus Koppel
    widget_find_by_name (Original Postin).

    Gruss, Andy

  8. #8
    Registrierter Benutzer Avatar von Rebell
    Registriert seit
    10.07.2002
    Ort
    Dresden
    Beiträge
    62
    Die Funktion von Glade sieht aber nicht abhängig aus
    Code:
    GtkWidget*
    lookup_widget                          (GtkWidget       *widget,
                                            const gchar     *widget_name)
    {
      GtkWidget *parent, *found_widget;
    
      for (;;)
        {
          if (GTK_IS_MENU (widget))
            parent = gtk_menu_get_attach_widget (GTK_MENU (widget));
          else
            parent = widget->parent;
          if (!parent)
            parent = (GtkWidget*) g_object_get_data (G_OBJECT (widget), "GladeParentKey");
          if (parent == NULL)
            break;
          widget = parent;
        }
    
      found_widget = (GtkWidget*) g_object_get_data (G_OBJECT (widget),
                                                     widget_name);
      if (!found_widget)
        g_warning ("Widget not found: %s", widget_name);
      return found_widget;
    }
    to be famous is so nice
    http://get-mike.de
    M:ke

  9. #9
    Registrierter Benutzer
    Registriert seit
    05.09.2002
    Ort
    Neuhausen
    Beiträge
    320
    Das muss neuer sein, dem 2.6.8er aus Debian Sarge liegt noch die Variante bei, welche mit einer globalen Widget-Liste arbeitet.

    Allerdings wird hier ein Datenfeld "GladeParentKey" benötigt, welches bei selbst händisch hinzugefügten Widgets kaum vorhanden sein wird.

    Gruss, Andy

  10. #10
    Registrierter Benutzer
    Registriert seit
    20.12.2004
    Beiträge
    26
    Zitat Zitat von RapidMax Beitrag anzeigen
    Wenn nicht die (veraltete) Code-Generierung von Glade verwendet wird, bietet das libglade API die Funktion glade_xml_get_widget().
    Soll man das wirklich verwenden. Hab mich nämlich schon gefragt warum man in glade3 keine Codegenerierung mehr hat. Entwerfe daher meine GUIs mit Glade3 und generiere sie dann mit Glade2. Verstehe einfach nicht wie das neue funktioniert!

    MFG THE_ONE

  11. #11
    Registrierter Benutzer Avatar von Rebell
    Registriert seit
    10.07.2002
    Ort
    Dresden
    Beiträge
    62
    Bei Glade3 stehen die Daten in einer XML-Datei die zur Laufzeit in GTK gerendet wird. Das hat den Vorteil, dass man die grafische Oberfläche ändern kann ohne neu zu compilieren.

    Im C-Code nutzt du dann die libglade-Bibliothek und lädst die Glade-Datei ein.
    Code:
    // Lade und Parse Glade-XML-Datei
    GladeXML *glade_app = glade_xml_new("test.glade", NULL, NULL);
    Das erzeugt dir automatisch die Anwendung. Mit
    Code:
    // Beziehe Hauptfenster aus der GTK-Struktur
    GtkWidget *window=glade_xml_get_widget(glade_app,"hauptfenster");
    // Zeige Hauptfenster an
    gtk_widget_show_all(window);
    ziehst du dir dann die einzelnen Widgets aus der GladeXML-Struktur. Ähnlich wie bei getElementById in JavaScript.
    Da macht den Code sauber und verständlich, sicherer und effektiver.
    Ich hab nen glade3-Beispiel da, wenn du das mal brauchst.
    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
  •