Partage
  • Partager sur Facebook
  • Partager sur Twitter

[GTK] envoyer des arguments aux signaux...

L'utilisatoin des arguments avec des pointeurs sur fonctions

Sujet résolu
    23 février 2006 à 20:36:01

    Salut !
    Depuis maintenant bien, deux jours, je lit un tutorial sur l'utilisatoin de la blibliothèque GTk+, pour faire des applis en mode fenêtré en C. Mais maintenant, je me heurte à un problème : comment envoyer des arguments aux fonctoins que l'on appelle avec les interuptions des signaux (p.e. quand on clique sur un bouton, il faut exécuter une fonction avec certains arguments.)

    Voici un code pour mieux m'expliquer :


    void *ma_fonction(int);
    int main(int argc, char **argv)
    {
        GtkWidget *pFenetre, *pBouton;
        gtk_init(&argc, &argv);
       
        pFenetre = gtk_window_new(GTK_WINDOW_TOPLEVEL);
        pBouton = gtk_button_add_with_label("Bouton");

        g_signal_connect(G_OBJECT(pBouton), "clicked", G_CALLBACK(ma_fonction), NULL);
    }


    Mais je me demandais à quel moment du signal il fallait que me mette l'argument, ou le pointeur vers argument...

    Voila, merci d'avance,

    Nico
    • Partager sur Facebook
    • Partager sur Twitter
      23 février 2006 à 21:25:46

      Salut, si j'ai bien compris pour envoyer des arguments tu fais:

      void *ma_fonction(int);
      int main(int argc, char **argv)
      {
          GtkWidget *pFenetre, *pBouton;
          gtk_init(&argc, &argv);
         
          pFenetre = gtk_window_new(GTK_WINDOW_TOPLEVEL);
          pBouton = gtk_button_add_with_label("Bouton");

          g_signal_connect(G_OBJECT(pBouton), "clicked", G_CALLBACK(ma_fonction), (ton argument);
      }
      • Partager sur Facebook
      • Partager sur Twitter
        25 février 2006 à 14:45:14

        Bah, c'est aussi ce que je pensais, mais le type du quatrième argument de cette fonctoin est imposé : gpointer ! (qui correspond au void du c standart). Ainsi, j'ai cru qu'il fallait faire un transtypage tout bête, mais soit je sais pas le faire (très probable), soit la subtilité est ailleurs...).

        Voici mon code, (il nessecite les bibliothèques GTK+ et pango), qui est censé ouvrir un popup avec comme titre le numéro du bouton sur lequel on a cliqué, mais apparement, il me renvoie plutôt une adresse mémoire ! Et ce, malgré& le fait que j'ai imposé de passer pour TOUS les boutons une seule variable, donc c'est n'est pas un problème de tableau...(et donc je comprends pas...)


        #include <stdlib.h>
        #include <gtk/gtk.h>

        void *OnClick(gpointer id);

        int main(int argc, char **argv)
        {
            int i;

            //Déclarations des GtkWidgets
            GtkWidget *pFenetre, *pHbox, *pVbox;
            GtkWidget *pBouton[4];
            gchar *sLabel;
            int un = 1, *pun = &un, deux = 2, *pdeux = &deux, trois = 3, *ptrois = &trois, quatre = 4, *pquatre = &quatre;

            //initialisation du mode GTK
            gtk_init(&argc, &argv);


            //Initialisation de la Fenetre
            pFenetre = gtk_window_new(GTK_WINDOW_TOPLEVEL);
            gtk_window_set_title(GTK_WINDOW(pFenetre), "Fenetre Principale");
            gtk_window_set_default_size(GTK_WINDOW(pFenetre), 320, 200);
            gtk_window_set_position(GTK_WINDOW(pFenetre), GTK_WIN_POS_CENTER);

            g_signal_connect(G_OBJECT(pFenetre), "destroy", G_CALLBACK(gtk_main_quit), NULL);

            //on initialise les 4 boutons grâce à une boucle !
            for(i = 1; i <= 4; i++)
            {
                sLabel = g_strdup_printf("Bouton n%d", i);
                pBouton[i-1] = gtk_button_new_with_label(sLabel);
                g_signal_connect(G_OBJECT(pBouton[i-1]), "clicked", G_CALLBACK(OnClick), (gpointer *) *pun);
            }

            //on initialise les Box
            pHbox = gtk_hbox_new(TRUE, 0);
            pVbox = gtk_vbox_new(TRUE,0);

            gtk_container_add(GTK_CONTAINER(pFenetre), pVbox);

            gtk_box_pack_start(GTK_BOX(pVbox), pBouton[0], TRUE, FALSE,0);
            gtk_box_pack_start(GTK_BOX(pVbox), pHbox, TRUE, FALSE,0);


            gtk_box_pack_start(GTK_BOX(pHbox), pBouton[1], TRUE, FALSE,0);
            gtk_box_pack_start(GTK_BOX(pHbox), pBouton[2], TRUE, FALSE,0);

            gtk_box_pack_start(GTK_BOX(pVbox), pBouton[3], TRUE, FALSE,0);
            //on montre le tout...
            gtk_widget_show_all(pFenetre);

            gtk_main();

            return 0;
        }

        void *OnClick(gpointer id)
        {
            GtkWidget *pWindow;
            gchar *sLabel;
            int rId = (int) (id);

            pWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL);

            sLabel = g_strdup_printf("Popup n%d", rId);
            gtk_window_set_title(GTK_WINDOW(pWindow), sLabel);
            gtk_window_set_default_size(GTK_WINDOW(pWindow), 250, 100);
            gtk_window_set_position(GTK_WINDOW(pWindow), GTK_WIN_POS_CENTER);
            gtk_widget_show(pWindow);
        }



        Merci d'avance (par contre, si vous voulez le compiler, il faut avoir les bibliotèques correspondantes...)
        • Partager sur Facebook
        • Partager sur Twitter
        Anonyme
          25 février 2006 à 14:52:26

          Transtipage incorecte :D
          Tu converti ldrsse en int, et non l valeur :D
          Comme sa que l'on fait :

          void *OnClick(gpointer id)
          {
              GtkWidget *pWindow;
              gchar *sLabel;
              //On converti le voir* vers un int*
              //On déréférence ensuite le pointeur(on obtien un int)
              //Mentenant moi j'irait lire la déclaration de gpointer dans un
              //header de WxWidget et je regarderait les commentaire
              //Car si ils voulait passer un int, ils utiliserait pas un gpointer
              //[Si tu veut mon avis gpointer est une structure, peutètre le widget qui a déclancher le onclick]
              int rId = *((int*)id);

              pWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL);

              sLabel = g_strdup_printf("Popup n%d", rId);
              gtk_window_set_title(GTK_WINDOW(pWindow), sLabel);
              gtk_window_set_default_size(GTK_WINDOW(pWindow), 250, 100);
              gtk_window_set_position(GTK_WINDOW(pWindow), GTK_WIN_POS_CENTER);
              gtk_widget_show(pWindow);
          }
          • Partager sur Facebook
          • Partager sur Twitter
          Anonyme
            25 février 2006 à 17:12:10

            Sinon un paramètre void *quelquechose, ça veut pas dire que que *quelquechose est un pointeur vers une variable de n'importe quel type ?
            • Partager sur Facebook
            • Partager sur Twitter
              25 février 2006 à 17:37:25

              non, void *quelquechose veut dire que _quelquechose_ (et non *quelquechose) est un pointeur vers n'importe quoi, une variable, une structure, etc...
              • Partager sur Facebook
              • Partager sur Twitter
                25 février 2006 à 17:38:12

                Citation : GuilOooo

                Sinon un paramètre void *quelquechose, ça veut pas dire que que *quelquechose est un pointeur vers une variable de n'importe quel type ?


                Les pointeurs de type void* sont générique, et pour avoir la valeur pointée faut forcément casté, enfin je laisse la place à rz0 pour expliquer ca plus en détail :D
                • Partager sur Facebook
                • Partager sur Twitter
                  25 février 2006 à 17:46:29

                  Nonon, faut pas forcément caster et on caste pas beaucoup (sinon jamais) les void * en C ; parce que ça a tendance à rendre le code plus lourd et puis quand on voit un cast on doit se poser dessus pour le comprendre (parce que si on le comprend mal, ça peut faire n'importe quoi...) alors qu'en fait c'est tout bête...

                  Ya conversion automatique à l'affectation entre void * et n'importe quel autre type de pointeur.

                  void *p;
                  int *a, x;
                  a = p;
                  x = *a;
                  Par exemple.
                  • Partager sur Facebook
                  • Partager sur Twitter
                    25 février 2006 à 17:53:12

                    Bah, merci pour toutes vos réponses(qui sont un peu sorties du sujet initiales, mais c'est toujours des infos utiles à savoir...).
                    Sinon, j'ai fini par trouver la réponse à mon problème : j'utilisais mal les fonctoins callbacks, ce qui me donnait un argument vers un pointeur qui était le widget au lieu d'être les données... Enfin, tout ça pour dire : "vous creusez plus la tête, mon problème est résolu".
                    Voici le code final :

                    void *OnClick(GtkWidget* pButton, gpointer arg)
                    {
                        GtkWidget *pWindow=NULL;
                        gchar* sLabel=NULL;

                        sLabel = malloc (128*sizeof(gchar));//allocation de la mémoire
                        pWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL);

                        strcpy (sLabel, gtk_button_get_label(GTK_BUTTON(pButton)));
                        /*raison inconnu, mais sprintf ne fonctionne pas... */
                        //sprintf(sLabel, "PopUp %c",sLabel[strlen(sLabel)-1]);
                        gtk_window_set_title(GTK_WINDOW(pWindow), sLabel);
                        gtk_window_set_default_size(GTK_WINDOW(pWindow), 250, 100);
                        gtk_window_set_position(GTK_WINDOW(pWindow), GTK_WIN_POS_CENTER);
                        gtk_widget_show(pWindow);
                         free (sLabel);
                    }


                    Encore merci
                    • Partager sur Facebook
                    • Partager sur Twitter
                      25 février 2006 à 18:13:55

                      rz0> bah si tu veux accéder à l'entier pointé par un void* t'es obligé de passer par un pointeur temporaire ? tu peux pas faire *(int*)p, par exemple ?
                      • Partager sur Facebook
                      • Partager sur Twitter
                        25 février 2006 à 18:30:44

                        Citation : asmanur

                        rz0> bah si tu veux accéder à l'entier pointé par un void* t'es obligé de passer par un pointeur temporaire ? tu peux pas faire *(int*)p, par exemple ?


                        Pas dis que tu pouvais pas mais en général ça favorise les erreurs et les constructions dures à lire. Après, dans l'absolu ce n'est pas impossible, surtout pour des valeurs simples comme ici ; mais la plupart du temps tu voudras garder un pointeur sur le vrai type et pas simplement une copie de la valeur pointée et dans ce cas là tu auras presque forcément un pointeur "temporaire" (sinon c'est illisible).
                        • Partager sur Facebook
                        • Partager sur Twitter

                        [GTK] envoyer des arguments aux signaux...

                        × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                        × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                        • Editeur
                        • Markdown