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 :

Aide à créer un bouton Play automatique!


Sujet :

GTK+ avec C & C++

  1. #1
    Candidat au Club
    Homme Profil pro
    Inscrit en
    Juin 2011
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juin 2011
    Messages : 4
    Points : 2
    Points
    2
    Par défaut Aide à créer un bouton Play automatique!
    Bonjour,

    Je suis en train de faire une interface gtk en langage C pour réaliser le "Jeu de la vie de Conway". Le programme ressemble cette flash:
    http://therese.eveilleau.pagesperso-...es/jeu_vie.swf

    Le problème est que je n'arrive pas à créer un bouton qui me permet de calculer et afficher automatique la génération suivante (comme le 3eme bouton dans le flash ci-dessus).

    J'ai essayé de créer un bouton et j'utilise la fonction g_signal_connect pour faire le callback. Mais j'arrive jamais à figer chaque génération pour l'afficher.

    Je vous remercie en avance pour vos réponses, et désolé pour mon français T__T.

  2. #2
    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
    Je ne comprends pas trop ton problème quand tu dis:
    j'arrive jamais à figer chaque génération pour l'afficher.
    Normalement, cliquer sur ton bouton doit juste appeler une fonction qui lance le timer de rafraichissement de ton image. Mettons que tu veux afficher la génération suivante au bout d'une seconde.

    1. connecter une callback à l'évènement "clicked" de ton bouton
    2. dans cette callback, appeler g_timeout_add_seconds avec une nouvelle callback, qui à chaque seconde, calculera une nouvelle génération.
    3. dans la même callback appelée par g_timeout_add_seconds, invalide ta GtkDrawingArea qui affiche l'état du jeu en appelant gtk_widget_queue_draw. Cela va déclencher l'émission de son évènement expose-event et forcer le dessin de la zone.
    4. dans la callback gérant l'expose-event de ta GtkDrawingArea, tu redessines tout d'après l'état en cours.
    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)

  3. #3
    Candidat au Club
    Homme Profil pro
    Inscrit en
    Juin 2011
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juin 2011
    Messages : 4
    Points : 2
    Points
    2
    Par défaut
    Citation Envoyé par liberforce Voir le message
    Je ne comprends pas trop ton problème quand tu dis:


    Normalement, cliquer sur ton bouton doit juste appeler une fonction qui lance le timer de rafraichissement de ton image. Mettons que tu veux afficher la génération suivante au bout d'une seconde.

    1. connecter une callback à l'évènement "clicked" de ton bouton
    2. dans cette callback, appeler g_timeout_add_seconds avec une nouvelle callback, qui à chaque seconde, calculera une nouvelle génération.
    3. dans la même callback appelée par g_timeout_add_seconds, invalide ta GtkDrawingArea qui affiche l'état du jeu en appelant gtk_widget_queue_draw. Cela va déclencher l'émission de son évènement expose-event et forcer le dessin de la zone.
    4. dans la callback gérant l'expose-event de ta GtkDrawingArea, tu redessines tout d'après l'état en cours.
    Merci de ta réponse, peut-être je n'ai pas bien expliqué mon problème. Voici mon code, comme ça c'est plus claire.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    g_signal_connect(G_OBJECT(pToggleBtn), "toggled", G_CALLBACK(OnBoucle),NULL);
    J'utilise un Toggle Button pour déclencher la fonction OnBoucle.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    void OnBoucle(GtkWidget *pToggle,gpointer data)
    {
        if ((pBouton[0][0]!=NULL)&&(pliste->gene<999)) //condition d'activer le bouton Play (pas important ^^)
        {
            while (*gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(pToggle))==TRUE)
            {
                pliste = GenerationSuiv(pliste); //calcule la génération suivante et l'ajouter dans une liste
                afficheTableau(pliste->tab); //pour tester dans le console
                attacher_Liste_Bouton(); //attacher la liste aux boutons (c.à.d les cellules) et rafraichir l'affichage
                g_usleep(1000000); //attendre avant calculer la génération après
            }
        }
    }
    Le problème est que:
    1/ Les boutons ne changent pas après chaque tour. Je sais que les calculs se passe bien car chaque seconde le tableau est affiché dans le console.

    2/ La boucle devient infinie car je ne peux pas agir sur le bouton pendant la fonction Callback.

    3/ Si je le teste avec une boucle finie (en utilisant un compteur i jusqu'à 5 générations par exemple), les boutons ne se mettent à jour juste après la boucle est finie, pas après chaque tour de la boucle.

    4/ Ici j'utilise les toggle boutons pour simuler les cellules d'une génération (toggled = TRUE => vivant), et ça sera trop lourd si je la mets à la taille 40x40. Est-ce qu'il y a d'autres méthodes? Qu'est ce que le GtkDrawingArea que tu as mentionné?

    Je ne comprends pas bien la méthode que tu me propose, tu peux m'expliquer plus détaillé? Merci ^^.

  4. #4
    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
    Oui, c'est assez logique que tu restes bloqué. Tu n'as pas compris le principe d'un toolkit à pompe à évènements. GTK, comme la plupart des toolkits gère des évènements. Tu as un tread principal (aussi appelé "boucle principale", ou "main loop") qui gère les différents évènements, et appelle les callbacks correspondantes.

    Si dans ta callback tu effectues des traitements longs, alors tu bloques toute la boucle principale. GTK ne peut pas traiter de nouveaux signaux tant que tu ne lui as pas "rendu la main", c'est à dire tant que tu n'es pas sorti de ta callback. D'om le fait que ton interface graphique est "gelée" (elle ne réagit plus).

    Ici le problème, c'est que tu essaies d'afficher toutes les images en réponse à l'appui sur le bouton. Tu bloques complètement la pompe à évènements. Le bon fonctionnement serait sur le click du bouton (transition OFF->ON) de lancer un timer. A chaque seconde, ce timer déclencherait un callback calculant uniquement la prochaine génération, indiquerait qu'il faut redessiner l'image, puis rendrait la main à la pompe à évènement.

    En cliquant à nouveau sur ton bouton (transition ON->OFF), il te suffira de détruire le timer, ce qui fait que la callback associée ne sera plus appelée.

    Une autre solution serait d'utiliser un thread de travail ("worker thread") pour faire le calcul des générations, mais quand tu débutes, se lancer dans les threads, c'est encore moins évident, et pas nécessairement la meilleure solution, sauf si tu recherches la performance brute et veux tirer parti des multiples coeurs de ton processeur.
    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)

  5. #5
    Candidat au Club
    Homme Profil pro
    Inscrit en
    Juin 2011
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juin 2011
    Messages : 4
    Points : 2
    Points
    2
    Par défaut
    Merci pour la réponse, c'est plus claire maintenant.

    Tu peux me dire comment pour lancer un timer? Est-ce qu'il y a une fonction spécifique ou il faut "include" une bibliothèque pour ça?

  6. #6
    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
    Je te l'ai déjà indiqué dans ma première réponse:
    pour un timer avec une granularité de l'ordre de la seconde, on utilise g_timeout_add_seconds. Pour un timer de l'ordre de la milliseconde, on utilise g_timeout_add. C'est en fait une source d'évènements qui vient alimenter la boucle principale. Quand un évènement indiquant que le temps est écoulé, la callback est appelée. Fais bien attention à la valeur que tu renvoies dans la callback, elle définit si elle doit continuer à être appelée ou si c'est la dernière fois.
    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)

  7. #7
    Candidat au Club
    Homme Profil pro
    Inscrit en
    Juin 2011
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juin 2011
    Messages : 4
    Points : 2
    Points
    2
    Par défaut
    Citation Envoyé par liberforce Voir le message
    Je te l'ai déjà indiqué dans ma première réponse:
    pour un timer avec une granularité de l'ordre de la seconde, on utilise g_timeout_add_seconds. Pour un timer de l'ordre de la milliseconde, on utilise g_timeout_add. C'est en fait une source d'évènements qui vient alimenter la boucle principale. Quand un évènement indiquant que le temps est écoulé, la callback est appelée. Fais bien attention à la valeur que tu renvoies dans la callback, elle définit si elle doit continuer à être appelée ou si c'est la dernière fois.
    Aaaaaaaaaaaaaaaaaaaaaaa j'ai réussi enfin, le code est beaucoup plus simple que j'ai pensé au début .

    Merci beaucoup liberforce, tu m'as aidé beaucoup avec mon projet

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Besoin d'aide pour créer des boutons de lecture
    Par bidays dans le forum Général JavaScript
    Réponses: 1
    Dernier message: 08/07/2012, 19h51
  2. Réponses: 1
    Dernier message: 18/02/2011, 19h38
  3. [Toutes versions] [Article] Créer un bouton d'aide contextuelle dans un formulaire Access
    Par argyronet dans le forum Access
    Réponses: 0
    Dernier message: 20/09/2010, 15h20
  4. [XLS-03] aide pour créer un bouton PRINT
    Par Biker-Robby dans le forum Excel
    Réponses: 4
    Dernier message: 13/01/2008, 17h47

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