IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

GTK+ avec C & C++ Discussion :

Callback, structures et boucle


Sujet :

GTK+ avec C & C++

  1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 14
    Points : 7
    Points
    7
    Par défaut Callback, structures et boucle
    Bonjour,

    j'ai déjà parcouru les forums et le net pour essayer de résoudre mon problème mais il est un petit peu différent de ceux liés au passage de structures simples dans un callback.

    Je génère un tableau de boutons à l'aide de deux boucles. Chaque bouton contient une image. J'aimerais changer d'image au clic sur le bouton à l'aide de la fonction : gtk_button_set_image(bouton,image);
    J'y arrive très bien pour un bouton simple, qui n'est pas compris dans un tableau et avec une image non stockée dans une structure .
    Or, mes images sont stockées dans un tableau d'images de la structure suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    typedef struct case_plateau
    {
        GtkWidget *image1[35];//image visible avant le clic
        GtkWidget *image2[35];//image visible après le clic
        GtkWidget *bouton[35];//bouton correspondant
        int i,j;
    }t_case;
    Voici mes boucles qui associent une image à chaque bouton :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    t_case case_jeu;
    for(case_jeu.i=0;case_jeu.i<6;case_jeu.i++)
        {
            for(case_jeu.j=0;case_jeu.j<6;case_jeu.j++)
            {
                init_image(&case_jeu,a,nb1,nb2);//appel de la fonction qui associe une image à chaque bouton
                case_jeu.boutton[case_jeu.j] = gtk_button_new();          gtk_button_set_image(case_jeu.boutton[case_jeu.j],case_jeu.image1[case_jeu.j]);//on associe l'image1 au bouton
                ...//ajout du bouton à la table
                g_signal_connect(G_OBJECT(case_jeu.boutton[case_jeu.j]), "clicked", G_CALLBACK(clic1_sur_case), &case_jeu);//je transmet ma structure à ma fonction callback
            }
        }
    Le tableau marche et les boutons contiennent bien image1. Image2[j] contient bien des images.
    J'aimerais maintenant associer dans mon fonction "clic1_sur_cas" mon image2 à mon bouton. Voilà ce que j'ai fait :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    void clic1_sur_case(GtkWidget *monbouton, gpointer data)
    {
        t_case *testcase = (t_case *)data;//Je cast data
    gtk_button_set_image(monbout->boutton[monbout->j],testcase.image2[testcase.j]);
    }
    Mon programme plante lorsque je clique sur le bouton.
    Pouvez-vous me dire où est-ce que je me suis trompé ?

    Je vous remercie d'avance.

  2. #2
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Janvier 2005
    Messages
    1 259
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 1 259
    Points : 1 633
    Points
    1 633
    Par défaut
    La structure "case_jeu" que tu transmets au callback sera la même pour tous tes boutons, donc ça ne va pas faire ce que tu veux. De plus j'ai la forte impression que c'est une variable locale à la fonction qui initialise tout, donc elle n'existera plus en mémoire quand tes callbacks seront appelés.

  3. #3
    Futur Membre du Club
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 14
    Points : 7
    Points
    7
    Par défaut
    Citation Envoyé par teuf13 Voir le message
    La structure "case_jeu" que tu transmets au callback sera la même pour tous tes boutons, donc ça ne va pas faire ce que tu veux.
    Quelle serait alors l'alternative ? Passer par deux structures différentes ?

    Citation Envoyé par teuf13 Voir le message
    De plus j'ai la forte impression que c'est une variable locale à la fonction qui initialise tout, donc elle n'existera plus en mémoire quand tes callbacks seront appelés.
    Pourtant la structure case_jeu qui passe par une fonction "void init(t_case * case_jeu)" me ressort bien les valeurs que je veux dans mon main.

  4. #4
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Janvier 2005
    Messages
    1 259
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 1 259
    Points : 1 633
    Points
    1 633
    Par défaut
    Citation Envoyé par cb450 Voir le message
    Quelle serait alors l'alternative ? Passer par deux structures différentes ?
    Je pense que j'allouerais une structure bcp plus simple à chaque itération dans la boucle qui contiendrait juste l'image avant/après pour le bouton auquel tu associes le callback. Beaucoup moins de risques de s'embrouiller avec les pointeurs en faisant comme ça.


    Citation Envoyé par cb450 Voir le message
    Pourtant la structure case_jeu qui passe par une fonction "void init(t_case * case_jeu)" me ressort bien les valeurs que je veux dans mon main.
    Pourtant ton programme plante pour des raisons mystérieuses Quand je dis "j'ai l'impression que", je veux dire que la façon dont t'as présenté ton code me donne cette impression, mais j'ai pas suffisammnet de code pour en être certain, donc c'est une invitation à vérifier ce point.

  5. #5
    Futur Membre du Club
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 14
    Points : 7
    Points
    7
    Par défaut
    Citation Envoyé par teuf13 Voir le message
    Pourtant ton programme plante pour des raisons mystérieuses Quand je dis "j'ai l'impression que", je veux dire que la façon dont t'as présenté ton code me donne cette impression, mais j'ai pas suffisamment de code pour en être certain, donc c'est une invitation à vérifier ce point.
    En fait, ma fonction callback "entre" bien dans ma fonction, j'ai fait les tests, ça marche sur toutes les cases[j]. Seulement, elle n'a pas l'air de bien transmettre ma structure à ma fonction ou alors je me plante à la réception.

    J'ai essayé avec un bouton à part et une structure "simplifiée".
    Ma structure (dans un .h) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    typedef struct case_jeu
    {
    int test;
    }t_case
    Mon main (en fait c'est une fonction, mais c'est dans celle là que je déclare ma variable de type t_case*)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    t_case case_jeu;
    case_jeu.test=20;
    GtkWidget *btn;
    ... //blabla, je crée le bouton
    g_signal_connect(G_OBJECT(btn), "clicked", G_CALLBACK(clic1_sur_case), &case_jeu);
    Ma fonction clic1_sur_case :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    void clic1_sur_case(GtkWidget *monbout, gpointer data)
    {
        t_case* testcase = (t_case*)data;
        printf("%d\n", testcase->t);
    }
    Ça m'affiche quelque chose(une adresse) mais pas mon nombre 20.
    Où est-ce que je me trompe, telle est la question

  6. #6
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Janvier 2005
    Messages
    1 259
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 1 259
    Points : 1 633
    Points
    1 633
    Par défaut
    Encore une fois, si tu fais

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
     
    void init (..) {
        t_case case_jeu;
    ...
        g_signal_connect(G_OBJECT(btn), "clicked", G_CALLBACK(clic1_sur_case), &case_jeu);
    ...
    }
     
    int main (int argc, char **argv) 
    {
    ...
        init (...);
        ...
        gtk_main();
    }
    Ca ne fonctionnera pas, au moment où ton signal est invoqué, case_jeu n'existe plus nul part

  7. #7
    Futur Membre du Club
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 14
    Points : 7
    Points
    7
    Par défaut
    Grosse erreur en effet. Maintenant, un int tout con de ma structure passe sans problème dans mon callback, je le récupère bien.
    Reste que je n'arrive pas à récupérer correctement mes infos en fonction de j. Or je ne peux pas vraiment trop faire autrement puisque si je n'initialise pas toutes mes images dès le départ, je ne pourrais pas imposer certaines conditions sur ma grille.

  8. #8
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Janvier 2005
    Messages
    1 259
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 1 259
    Points : 1 633
    Points
    1 633
    Par défaut
    Si tu veux recevoir des données différentes en fonction du bouton sur lequel on clique, soit tu retrouves la valeur de j en utilisant le GtkButton que tu récupères en argument de ton callback, soit tu passes une structure différente pour chaque bouton quand tu assignes les callbacks. La tu passes un pointeur sur la même instance de la structure à chaque fois, donc au final, quel que soit le bouton tu verras les mêmes données.

  9. #9
    Membre à l'essai
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    45
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 45
    Points : 17
    Points
    17
    Par défaut
    Tu as essayé en faisant plutôt un tableau de structure ?

    Du genre...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    typedef struct t_bouton
    {
        GtkWidget *pImage;
        GtkWidget *pButton;
    }t_bouton;
    Après tu mets ce que tu veux dedans, un gint etat; associé au bouton pour savoir quel pipe tu as

    Et en déclaration dans le main :

  10. #10
    Futur Membre du Club
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 14
    Points : 7
    Points
    7
    Par défaut
    Le tableau de structures semble être la bonne solution mais un problème persiste.
    Voilà ce que j'ai fait :
    Ma structure :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    typedef struct bouton
    {
        GtkWidget *image;
        GtkWidget *monbouton;
        int etat;
    }t_bouton;
    Main :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    t_bouton bouton[36];
    int i,j;
     
    for(i=0;i<36;i++)
    {
      for(j=0;j<36;j++)
      {
       ...//initialisation du tableau avec images etc...
        bouton[j].etat=j;
        bouton[bouton->etat].etat=bouton[j].etat;//en gros, je donne à etat la valeur de j
     g_signal_connect(G_OBJECT(bouton[j].monbouton), "clicked", G_CALLBACK(clic1_sur_case), &bouton);//lorsque je clique sur mon bouton j
      }
    }
    Ma fonction :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    void clic1_sur_case(GtkWidget *monbout, gpointer data)
    {
        t_case* testcase = (t_case*)data;
        printf("%d\n", testcase[testcase->etat].etat);
    }
    Le problème est que testcase[testcase->etat].etat m'affiche 5 puisque c'est le dernier j de ma boucle. Or j'aimerais qu'il m'affiche le jième bouton sur lequel j'appuie.
    Je sens que je suis pas loin mais que je prend le problème à l'envers.

  11. #11
    Membre à l'essai
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    45
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 45
    Points : 17
    Points
    17
    Par défaut
    Bon alors déjà il y a un truc que je capte pas.

    Notre plateau de jeu c'est bien du 6*6 non ?

    Donc tu devrais avoir une double boucle avec i allant de 0 à 6 et de même pour j...

    Ensuite, ce n'est pas un tableau de pointeurs sur structures, mais un tableau de structures, donc il ne devrait pas y avoir de "->" non ?

  12. #12
    Futur Membre du Club
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 14
    Points : 7
    Points
    7
    Par défaut
    Oui, c'est du 6 par 6, simple erreur quand j'ai recopié ici.
    Après, je t'avouerais que j'ai mis les "->" parce que ça ne passe pas à la compil autrement.

    En fait, ma structure contient deux gtkwidget image (image1 et image2) dont un contient les faces cachées et l'autre les pipes. J'initialise tout avant puisqu'il y a certaines conditions sur les pipes(aléatoire, bombe et explosif) mais je n'affiche que la face cachée au départ(ce qui marche).
    En théorie, je n'ai plus qu'à remplacer l'image 2 qui est déjà initialisée dans le bouton correspondant.

    Je fais peut-être une erreur dans mon raisonnement mais as-tu procédé de la même façon, avec un tableau de structure ?

  13. #13
    Membre à l'essai
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    45
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 45
    Points : 17
    Points
    17
    Par défaut
    Désolé du temps de réponse, je travaillais sur la fonction callback.

    Donc moi j'utilise bien un tableau de structures avec dedans :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    GtkWidget *pImage;
    GtkWidget *button;
    gint etat;
    Dans mon main j'ai t_boutons cases[37]; (j'ai mis une case en plus pour la zone de swap)

    Mon gint etat je l'ai mis au cas où, j'en aurais peut-être pas besoin en fait.

    J'ai mis un signal pour chaque button, lors de l'initialisation de ces derniers (avec association d'image etc).
    Je passe l'adresse du premier élément de mon tableau de structures pour la fonction callback.
    J'ai un truc du genre g_signal_connect(........, G_CALLBACK(callback_swap), cases);

    Pour la fonction callback, tu récupères le widget en question (le bouton) et ton paramètre que tu as décidé de passer, donc le tableau de structures.

  14. #14
    Futur Membre du Club
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 14
    Points : 7
    Points
    7
    Par défaut
    En fait, dans le main, faut initialiser la structure comme ça plutôt :
    t_boutons cases[7][7];
    Autrement on perd toutes les données du bouton en question pour la suite puisque quand tu crées le tableau, tu crées juste un cases.bouton[j].
    En fait, j'écrasais à chaque fois dans ma boucle le j en question. Comme pour le puissance4 finalement.
    T'avais fais attention à ça ?

  15. #15
    Membre à l'essai
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    45
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 45
    Points : 17
    Points
    17
    Par défaut
    Citation Envoyé par cb450 Voir le message
    En fait, dans le main, faut initialiser la structure comme ça plutôt :
    t_boutons cases[7][7];
    Autrement on perd toutes les données du bouton en question pour la suite puisque quand tu crées le tableau, tu crées juste un cases.bouton[j].
    En fait, j'écrasais à chaque fois dans ma boucle le j en question. Comme pour le puissance4 finalement.
    T'avais fais attention à ça ?
    Mouarf
    Pas bête, j'aurais du y penser non de diou !

    Oui c'est vrai qu'après pour le test de victoire ça risque d'être bordélique...

  16. #16
    Futur Membre du Club
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 14
    Points : 7
    Points
    7
    Par défaut
    J'ai réussi.
    Si ça peut aider des gens, voilà quelles ont été mes erreurs :
    - ne pas avoir gardé la structure d'une fonction callback
    - ne pas avoir mis mes signaux dans le main (erreur de débutant)
    - utiliser des tableaux dans une structure au lieu d'un tableau de structure
    - perdre les infos de mes boutons dans mes boucles par remplacement des j (utiliser un tableau revient à penser aux 2 dimensions [i][j], c'est logique mais on n'y pense pas toujours)
    - ne pas avoir envoyé les coordonnées d'une des "cases" du tableau de structures à ma fonction callback (bien mettre en paramètre &mastruct[i][j] en dernier paramètre du signal)

    Merci lowwa et teuf pour votre aide

  17. #17
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Janvier 2005
    Messages
    1 259
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 1 259
    Points : 1 633
    Points
    1 633
    Par défaut
    Citation Envoyé par cb450 Voir le message
    - ne pas avoir mis mes signaux dans le main (erreur de débutant)
    Pas sûr de ce que tu entends par là, j'ai tendance à mettre le moins de choses possibles dans mon main, et l'enregistrement des signaux ne fait pas partie des choses que je mets en priorité à cet endroit

  18. #18
    Expert confirmé
    Avatar de gerald3d
    Homme Profil pro
    Conducteur de train
    Inscrit en
    Février 2008
    Messages
    2 291
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Conducteur de train
    Secteur : Transports

    Informations forums :
    Inscription : Février 2008
    Messages : 2 291
    Points : 4 941
    Points
    4 941
    Billets dans le blog
    5
    Par défaut
    Citation Envoyé par teuf13 Voir le message
    Pas sûr de ce que tu entends par là, j'ai tendance à mettre le moins de choses possibles dans mon main, et l'enregistrement des signaux ne fait pas partie des choses que je mets en priorité à cet endroit
    Je suis d'accord.
    Pour exemple voila le genre de "main();" que j'écris:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    int main (int argc, char *argv[])
    {
    	gtk_init (&argc, &argv);
     
    	PGUI = g_try_new(Spointer, 1);
     
    	if (PGUI)
    	{
    		create_window ();
    		gtk_main ();
    		return 0;
    	}
    	g_printerr("Allocation mémoire impossible!\n");
    	return 1;
    }

  19. #19
    Modérateur

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2009
    Messages
    1 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2009
    Messages : 1 395
    Points : 2 002
    Points
    2 002
    Par défaut
    Hum... J'aime pas trop ce style, je préfère plutôt tester l'erreur avant le cas nominal, pour faciliter la lecture :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    int main (int argc, char *argv[])
    {
    	gtk_init (&argc, &argv);
     
    	PGUI = g_try_new(Spointer, 1);
     
    	if (PGUI == NULL)
    	{
    		g_printerr("Allocation mémoire impossible!\n");
    		return 1;
    	}
     
    	create_window ();
    	gtk_main ();
    	return 0;
    }
    M'enfin dans le cas présent, si c'est pour quitter si l'allocation ne fonctionne pas, autant utiliser g_new plutôt que g_try_new...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    int main (int argc, char *argv[])
    {
    	gtk_init (&argc, &argv);
    	PGUI = g_new(Spointer, 1);
     	create_window ();
    	gtk_main ();
    	return 0;
    }
    Documentation officielle GTK+ 3:
    GTK en C, GTK en Python

    Tutoriels GTK+ 3:
    GTK en C, GTK en Python

    Tutoriels par l'exemple (platform-demos):
    GTK (tous langages)

  20. #20
    Expert confirmé
    Avatar de gerald3d
    Homme Profil pro
    Conducteur de train
    Inscrit en
    Février 2008
    Messages
    2 291
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Conducteur de train
    Secteur : Transports

    Informations forums :
    Inscription : Février 2008
    Messages : 2 291
    Points : 4 941
    Points
    4 941
    Billets dans le blog
    5
    Par défaut
    Histoire de chipoter g_new(); crash l'application. Pas très propre comme fin!

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. Structure en boucle des fichiers plats.
    Par Domingo60 dans le forum SQL*Loader
    Réponses: 1
    Dernier message: 15/10/2010, 14h29
  2. Callback dans une boucle for
    Par bellionth dans le forum Interfaces Graphiques
    Réponses: 2
    Dernier message: 18/06/2010, 09h42
  3. Commande Structure et boucle FOR
    Par angelevil dans le forum Windows Forms
    Réponses: 2
    Dernier message: 30/08/2009, 01h10
  4. [AC-2007] Structure de boucle
    Par louroulou dans le forum VBA Access
    Réponses: 3
    Dernier message: 26/08/2009, 09h15
  5. [Débutant] Structure et boucles
    Par rob408231 dans le forum MATLAB
    Réponses: 2
    Dernier message: 05/04/2009, 20h30

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo