Callback Funktionsparameter



  • Hi,
    ich sammle gerade meine ersten Erfahrungen mit GTK, und habe folgendes Problem:

    Ich möchte über einen Callback eine Funktion aufrufen die zwei Parameter aus zwei Textfeldern bekommen soll, aber irgendwie bekomm ich es nicht hin... Mit g_signal_connect kann ich ja mit dem letzten Parameter einen Parameter für die Callback-Funktion festlegen, und das klappt auch mit einem... Aber was mache ich denn nun wenn ich mehrere Parameter verwenden möchte?!

    Hier einfach mal mein bisheriges Programm:

    #include <stdio.h>
    #include <stdlib.h>
    #include <gtk/gtk.h>
    #include <string>		
    
    using namespace std;
    
    // Wird beim Beenden des Programms aufgerufen 
    void gtk_main_quit() {
      printf ("Quit Programm\n");
      exit(0);
    }
    
    static void ggT(GtkWidget *widget, GtkWidget *aInput, GtkWidget *bInput) {
    
    	gint a = (gint)gtk_entry_get_text(GTK_ENTRY(aInput));
    	gint b = (gint)gtk_entry_get_text(GTK_ENTRY(bInput));
    
    	printf ("Calculate GCD(%i, %i)\n", a, b);
    
    	return;
    }
    
    int main(int argc, char *argv[]) {
    
        GtkWidget *window;
        GtkWidget *vbox, *hbox, *aHBox, *bHBox, *ggTHBox;
        GtkWidget *aInput, *bInput, *ggTInput;
        GtkWidget *closeButton, *calculateButton;
        GtkWidget *check;
    
        GtkWidget *programLabel, *aLabel, *bLabel, *ggTLabel;
    
        gint tmp_pos;
    
        gtk_init (&argc, &argv);
    
    	// Fenstervariablen
    	int windowWidth = 250;
    	int windowHeight = 200;
    	const gchar *windowTitle = "VDK - Aufgabe 03a";
    
        // Fenster erstellen
        window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
        gtk_widget_set_size_request (GTK_WIDGET (window), windowWidth, windowHeight);
        gtk_window_set_title (GTK_WINDOW (window), windowTitle);
    
        g_signal_connect (G_OBJECT (window), "destroy", G_CALLBACK (gtk_main_quit), NULL);
        g_signal_connect_swapped (G_OBJECT (window), "delete_event", G_CALLBACK (gtk_widget_destroy), G_OBJECT (window));
    
    	// --------------------------------------------------------------
    
    	// Vertikales Layout erstellen
        vbox = gtk_vbox_new(FALSE, 0);
        gtk_container_add (GTK_CONTAINER(window), vbox);
        gtk_widget_show(vbox);
    
    	// Programm Label erstellen, platzieren und anzeigen
    	programLabel = gtk_label_new("Grösster gemeinsame Teiler");
    	gtk_box_pack_start (GTK_BOX (vbox), programLabel, TRUE, TRUE, 0);
    	gtk_widget_show(programLabel);
    
    	// --------------------------------------------------------------
    
    	// a Horizontales Layout erstellen
        aHBox = gtk_hbox_new (FALSE, 0);
        gtk_container_add (GTK_CONTAINER (vbox), aHBox);
        gtk_widget_show(aHBox);
    
        // a Label erstellen, platzieren und anzeigen
    	aLabel = gtk_label_new("a: ");
    	gtk_box_pack_start (GTK_BOX (aHBox), aLabel, TRUE, TRUE, 0);
    	gtk_widget_show(aLabel);
    
    	// a Eingabefeld erstellen
        aInput = gtk_entry_new ();
        // Max. Zeichenlänge auf 10 beschränken
        gtk_entry_set_max_length (GTK_ENTRY (aInput), 10);
    
        //g_signal_connect (G_OBJECT (aInput), "activate", G_CALLBACK (ggT), (gpointer) aInput);
        gtk_entry_set_text (GTK_ENTRY (aInput), "12");
    	gtk_box_pack_start (GTK_BOX (aHBox), aInput, TRUE, TRUE, 0);
        gtk_widget_show (aInput);
    
    	// --------------------------------------------------------------
    
    	// b Horizontales Layout erstellen
        bHBox = gtk_hbox_new (FALSE, 0);
        gtk_container_add (GTK_CONTAINER (vbox), bHBox);
        gtk_widget_show(bHBox);
    
        // b Label erstellen, platzieren und anzeigen
    	bLabel = gtk_label_new("b: ");
    	gtk_box_pack_start (GTK_BOX (bHBox), bLabel, TRUE, TRUE, 0);
    	gtk_widget_show(bLabel);
    
    	// b Eingabefeld erstellen
        bInput = gtk_entry_new ();
        // Max. Zeichenlänge auf 10 beschränken
        gtk_entry_set_max_length (GTK_ENTRY (bInput), 10);
    
        //g_signal_connect (G_OBJECT (bInput), "activate", G_CALLBACK (ggT), (gpointer) bInput);
        gtk_entry_set_text (GTK_ENTRY (bInput), "40");
        /*tmp_pos = GTK_ENTRY (bInput)->text_length;
        gtk_editable_insert_text (GTK_EDITABLE (bInput), " world", -1, &tmp_pos);
        gtk_editable_select_region (GTK_EDITABLE (bInput), 0, GTK_ENTRY (bInput)->text_length);
        */
        gtk_box_pack_start (GTK_BOX (bHBox), bInput, TRUE, TRUE, 0);
        gtk_widget_show (bInput);
    
    	// --------------------------------------------------------------
    
    	// ggT Horizontales Layout erstellen
        ggTHBox = gtk_hbox_new (FALSE, 0);
        gtk_container_add (GTK_CONTAINER (vbox), ggTHBox);
        gtk_widget_show(ggTHBox);
    
        // ggT Label erstellen, platzieren und anzeigen
    	ggTLabel = gtk_label_new("ggT: ");
    	gtk_box_pack_start (GTK_BOX (ggTHBox), ggTLabel, TRUE, TRUE, 0);
    	gtk_widget_show(ggTLabel);
    
    	// ggT Eingabefeld erstellen
        ggTInput = gtk_entry_new ();
        // Max. Zeichenlänge auf 10 beschränken
        gtk_entry_set_max_length (GTK_ENTRY (ggTInput), 10);
    
        //g_signal_connect (G_OBJECT (ggTInput), "activate", G_CALLBACK (ggT), (gpointer) ggTInput);
    	// Textfeld nicht editierbar machen
    	gtk_editable_set_editable (GTK_EDITABLE (ggTInput), FALSE);
        gtk_box_pack_start (GTK_BOX (ggTHBox), ggTInput, TRUE, TRUE, 0);
        gtk_widget_show (ggTInput);
    
    	// --------------------------------------------------------------
    
    	// Berechnen Button                
        calculateButton = gtk_button_new_with_label("ggT berechnen");
        g_signal_connect (G_OBJECT (calculateButton), "clicked", G_CALLBACK (ggT), G_OBJECT (window));
        gtk_box_pack_start (GTK_BOX (vbox), calculateButton, TRUE, TRUE, 0);
        //GTK_WIDGET_SET_FLAGS (calculateButton, GTK_CAN_DEFAULT);
        //gtk_widget_grab_default (calculateButton);
        gtk_widget_show (calculateButton);
    
    	// Schliessen Button                
        closeButton = gtk_button_new_from_stock (GTK_STOCK_CLOSE);
        g_signal_connect_swapped (G_OBJECT (closeButton), "clicked", G_CALLBACK (gtk_widget_destroy), G_OBJECT (window));
        gtk_box_pack_start (GTK_BOX (vbox), closeButton, TRUE, TRUE, 0);
        GTK_WIDGET_SET_FLAGS (closeButton, GTK_CAN_DEFAULT);
        gtk_widget_grab_default (closeButton);
        gtk_widget_show (closeButton);
    
        gtk_widget_show (window);
    
        gtk_main();
    
        return 0;
    }
    

    Freue mich über jeden Tip 🙂



  • Hi,

    die Lösung deines Problems ist simpel: Du kapselst mehrere Werte mit einem struct:

    typedef struct {
      int alter;
      char vorname[30];
    } Foo;
    

    🙂

    MfG

    GPC



  • Hi...
    Danke für Deine Antwort.
    Macht man es denn so im Allgemeinen?
    Ich war jetzt auf die Idee gekommen die Variablen die ich brauche einfach global zu halten. Was bei späteren grösseren Projekten vielleicht unschön wird.
    Bei vielen Funktionen mit unterschiedlichen Parametern jedesmal die benötigten Parameter in eine Struktur zu verpacken ist vielleicht eine Lösung, aber auch nicht das Eleganteste oder sehe ich das falsch.

    Für weitere Tipps bin ich immer zu haben 😋



  • startupboy schrieb:

    Hi...
    Danke für Deine Antwort.
    Macht man es denn so im Allgemeinen?

    Zumindest ich mach das so im Allgemeinen. Du kannst dir aber auch gerne OpenSource Programme, die mit GTK+ geschrieben wurden, ansehen und wirst da "Ähnlichkeiten" finden 😉

    Ich war jetzt auf die Idee gekommen die Variablen die ich brauche einfach global zu halten.

    Schlechte Idee.

    Was bei späteren grösseren Projekten vielleicht unschön wird.

    Mit Sicherheit.

    Bei vielen Funktionen mit unterschiedlichen Parametern jedesmal die benötigten Parameter in eine Struktur zu verpacken ist vielleicht eine Lösung, aber auch nicht das Eleganteste oder sehe ich das falsch.

    Na ja, es ist eine Art "OOC" ➡ Objektorientierte Programmierung in C. Man gibt eben seine Instanzen rum, so wie man's in C++ auch macht. GTK+ versteht sich ja auch als objektorientiertes Toolkit (dafür steht auch das +; das es in C geschrieben ist, ist egal).

    Und mir persönlich liegt dieser Stil sehr.

    MfG

    GPC



  • Stimmt schon...
    Vielleicht sollte ich mein Programm mehr auf OOP ausrichten, und dann einfach ein Objekt übergeben oder Deinen Tipp mit der Struktur befolgen.

    🙂


Log in to reply