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+ Discussion :

Faut-il utiliser Glade avec GTK3 ?


Sujet :

GTK+

  1. #1
    Membre à l'essai
    Homme Profil pro
    Ingénieur informatique
    Inscrit en
    Novembre 2018
    Messages
    31
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2018
    Messages : 31
    Points : 10
    Points
    10
    Par défaut Faut-il utiliser Glade avec GTK3 ?
    Bonsoir,

    je travaille en ce moment sur un projet en C où j'utilise GTK3 pour interagir avec l'utilisateur.

    De ce fait, j'aimerais par exemple créer des boutons et des champs de texte pour ainsi récupérer les données que l'utilisateur aura rentré.
    J'aimerais aussi déclencher une fonction et envoyer des paramètres à celle-ci en cliquant sur un bouton.

    Je pensais donc utiliser Glade pour faire des interfaces graphiques plus rapidement mais j'avoue que je suis un petit peu perdu. J'ai beau avoir lu le tutoriel, je ne comprends toujours pas comment récupérer une donnée d'un champ texte, et je suis tombé sur des articles disant que l'utilisation de Glade et des signaux est limitée.

    Qu'est-ce que vous me conseilleriez d'utiliser dans mon cas ?

    Merci.

  2. #2
    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
    Bonjour.

    Avant d'utiliser Glade il est bon d'essayer de construire son interface directement dans le code source. Si cette première étape ne te pose aucun problème, je sous-entends aussi par là récupérer les données et interactions des différents widgets qui la compose, alors tu peux passer à l'étape suivante qui est l'utilisation de Glade.

    Regarde dans ma signature il y a un lien sur un tuto que j'ai écrit il y a un petit moment déjà.

  3. #3
    Membre à l'essai
    Homme Profil pro
    Ingénieur informatique
    Inscrit en
    Novembre 2018
    Messages
    31
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2018
    Messages : 31
    Points : 10
    Points
    10
    Par défaut
    Merci beaucoup pour ta réponse,

    effectivement j'ai déjà lu ton tutoriel, et merci d'ailleurs, mais je suis bloqué à partir des signaux et particulièrement des user_data, en fait je ne comprends pas comment transmettre plusieurs données au lieu d'une même si je sais qu'il faut utiliser une structure apparemment.

  4. #4
    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
    Créer une structure permet d'encapsuler plusieurs données accessible à une seule adresse.

    Comme le "user_data" des fonctions callbacks de Gtk+ est un pointeur sur une adresse, il te suffit de transmettre l'adresse de la variable qui aura comme type la structure de ton choix.

    Exemple:

    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
    // Déclaration d'une structure
    #typedef struct {
    int a;
    int b;
    int c;
    } Structure;
    
    // Déclaration d'une variable de type Structure
    Structure variable;
    
    // Déclaration d'un GtkButton pour l'exemple
    GtkWidget *button = gtk_button_new_with_label ("bouton");
    
    // Affectation d'un callback au signal "clicked" du bouton. On transmet à ce callback l'adresse de la variable "variable"
    g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (cb_clicked), &variable);
    Dans la fonction cb_clicked(); on récupère l'adresse de variable.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    void cb_clicked (GtkButton *button, gpointer user_data)
    {
      Structure *variable = (Structure*) user_data; // Casting du pointeur générique récupéré
     
      variable->a = 10;
      variable->b = 20;
      variable->c = 30;
    }
    Il est possible de caster directement les pointeurs transmis ce qui raccourci un peu le code et donne plus de lisibilité.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    void cb_clicked (GtkButton *button, Structure *variable)
    {
      variable->a = 10;
      variable->b = 20;
      variable->c = 30;
    }

  5. #5
    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
    Personnellement, je recommande ceci:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    void cb_clicked (GtkButton *button, gpointer user_data)
    {
      Structure *variable = user_data;
     
      variable->a = 10;
      variable->b = 20;
      variable->c = 30;
    }
    Pas de cast explicite, car un gpointer est un void* et se caste vers tout type de pointer. Pas de changement de la signature de la fonction, ce qui permet à la lecture de bien voir que c'est un paramètre user_data où on peut passer ce qu'on veut et pas un paramètre obligatoire du signal.
    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)

  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
    Si tu débutes, le plus simple est sans doute de créer ton interface avec glade, et de connecter tes signaux manuellement dans ton programme, avec g_signal_connect. C'est le meilleur compromis quand on débute je pense. Pas besoin de spécifier le nom de tes callbacks dans les widgets de ton fichier glade. Essaie déjà comme cela de gérer un cas simple: créer une fenêtre avec un bouton à l'intérieur qui fait affiche quelque chose sur la console quand on clique dessus.
    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
    Membre à l'essai
    Homme Profil pro
    Ingénieur informatique
    Inscrit en
    Novembre 2018
    Messages
    31
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2018
    Messages : 31
    Points : 10
    Points
    10
    Par défaut
    Merci beaucoup pour ces nombreuses réponses, vous m'avez bien aidé !

    Je vais m'entraîner et je reviendrais vers vous si j'ai des problèmes et que je n'arrive pas à résoudre.

    Merci encore.

  8. #8
    Membre à l'essai
    Homme Profil pro
    Ingénieur informatique
    Inscrit en
    Novembre 2018
    Messages
    31
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2018
    Messages : 31
    Points : 10
    Points
    10
    Par défaut
    Bon, alors j'ai réussi à afficher un message quand on clique sur un bouton sans trop de soucis mais maintenant je n'arrive pas à afficher le texte d'un label quand je clique sur un bouton. J'ai aussi quelques questions.

    Tout d'abord, je déclare un pointeur GtkWiget *label dans lequel je vais ranger mon widget label qui est dans glade. Déjà ici, est-ce que je devrais le déclarer en GtkWidget *label ou plutôt GtkLabel *label ?

    Par le suite j'ai donc ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    label = GTK_WIDGET(gtk_builder_get_object(builder, "myLabel"));
    Ici encore, je ne sais pas si je dois mettre GTK_WIDGET ou GTK_LABEL.

    Ensuite, j'affecte un signal à mon bouton :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    g_signal_connect(button,"clicked",G_CALLBACK(print_label),label);
    Où ma fonction label est comme ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    void print_label(GtkButton *button, gpointer user_data)
    {
        GtkWidget *label = user_data;
        g_print(gtk_label_get_label(GTK_LABEL(label)));
    }
    Bien-sûr ça ne fonctionne pas. J'ai compris comment faire passer une structure mais je ne sais même pas comment faire passer un simple pointeur.
    De plus, je ne comprends pas très bien le premier argument de la fonction print_label que j'ai mis car on le retrouve dans tous les callbacks que j'ai vu : GtkButton *button.
    Je ne vois ni à quoi il sert, ni ce qu'il contient car on envoie aucune données sur ce paramètre ou alors je ne le trouve pas ?

    Merci.

    PS: comment fait-on pour écrire du code dans une balise faite pour ça sur le forum ?

  9. #9
    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 JeremTer Voir le message
    Bon, alors j'ai réussi à afficher un message quand on clique sur un bouton sans trop de soucis mais maintenant je n'arrive pas à afficher le texte d'un label quand je clique sur un bouton. J'ai aussi quelques questions.

    Tout d'abord, je déclare un pointeur GtkWiget *label dans lequel je vais ranger mon widget label qui est dans glade. Déjà ici, est-ce que je devrais le déclarer en GtkWidget *label ou plutôt GtkLabel *label ?
    Par principe la plupart, pour ne pas dire tous les widgets, dérivent de GtkWidget. Donc, lorsque tu récupères l'un d'eux via gtk_builder_get_object (); il est de bon ton de le caster en GtkWidget.

    Citation Envoyé par JeremTer Voir le message
    Par le suite j'ai donc ça : label = GTK_WIDGET(gtk_builder_get_object(builder, "myLabel"));

    Ici encore, je ne sais pas si je dois mettre GTK_WIDGET ou GTK_LABEL.
    La réponse précédente répond aussi à cette question . Ce sera donc GTK_WIDGET.

    Citation Envoyé par JeremTer Voir le message
    Ensuite, j'affecte un signal à mon bouton : g_signal_connect(button,"clicked",G_CALLBACK(print_label),label);

    Où ma fonction label est comme ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    void print_label(GtkButton *button, gpointer user_data)
    {
        GtkWidget *label = user_data;
        g_print(gtk_label_get_label(GTK_LABEL(label)));
    }
    Étonnant parce que ce code est correcte. Il faudrait peut-être que tu nous montres tout ton code pour que l'on comprenne où est l'erreur.

    Citation Envoyé par JeremTer Voir le message
    Bien-sûr ça ne fonctionne pas. J'ai compris comment faire passer une structure mais je ne sais même pas comment faire passer un simple pointeur.
    De plus, je ne comprends pas très bien le premier argument de la fonction print_label que j'ai mis car on le retrouve dans tous les callbacks que j'ai vu : GtkButton *button.
    Je ne vois ni à quoi il sert, ni ce qu'il contient car on envoie aucune données sur ce paramètre ou alors je ne le trouve pas ?

    Merci.
    Il apparaît au vu de ton commentaire que la notion de pointeur n'est pas tout à fait maîtrisé. Un pointeur te permet de connaître l'adresse de n'importe quelle donnée. Cette donnée peut être un widget, une variable, une structure... Donc, tu transmets toujours un pointeur qui contient l'adresse de l'élément que tu désires manipuler.

    Les prototypes de callbacks associés aux différents signaux des GtkWidget que tu utilises commencent toujours par un pointeur sur le widget qui a reçu le dit signal. Donc, dans ton exemple, tu récupères l'adresse du bouton sur lequel tu as cliqué. C'est magique ... enfin, pas tout à fait. Mais pour l'instant prends ce principe pour acquis.

    Citation Envoyé par JeremTer Voir le message
    PS: comment fait-on pour écrire du code dans une balise faite pour ça sur le forum ?
    C'est tout simple . Tu as une icône avec un # à l'intérieur dans la barre d'outils de l'édition d'un post. Tu cliques dessus, il insert les balises "quote /quote" à l'endroit du curseur. Tu peux aussi sélectionner un texte et cliquer ensuite sur l'icône. Ton texte sera encadré des balises.

  10. #10
    Membre à l'essai
    Homme Profil pro
    Ingénieur informatique
    Inscrit en
    Novembre 2018
    Messages
    31
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2018
    Messages : 31
    Points : 10
    Points
    10
    Par défaut
    Merci beaucoup !

    Alors entre temps j'ai finalement remarqué mon erreur, c'est tout simplement que j'ai confondu label et entry. Je pensais que pour récupérer le texte d'un champ de texte, il fallait faire gtk_label_get_label alors que j'ai réussi avec gtk_entry_get_text.

    Si j'ai bien compris, un label c'est un texte qui est déjà sur un élément comme un bouton par exemple, alors qu'à chaque fois que je demande à un utilisateur de m'écrire quelque chose dans un champ texte c'est un entry ?

  11. #11
    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
    tout à fait

  12. #12
    Membre à l'essai
    Homme Profil pro
    Ingénieur informatique
    Inscrit en
    Novembre 2018
    Messages
    31
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2018
    Messages : 31
    Points : 10
    Points
    10
    Par défaut
    J'ai une autre question, j'essaye de faire un compte à rebours et de l'afficher en tant que label sur une fenêtre Gtk (car je ne vois pas comment faire autrement).

    J'ai donc une fonction pour décompter un nombre de un en un :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    int countdown(int beginningValue)
    {
        if(beginningValue > 0)
            beginningValue--;
        return beginningValue;
    }
    ainsi qu'une fonction qui affiche le nombre sur le label :
    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 printCountdown(GtkWidget *button,GtkWidget *myLabel)
    {
        const char *labelValue;
        int value;
        char arrayValue[5];
        labelValue = gtk_label_get_text(GTK_LABEL(myLabel));
        value = atoi(labelValue);
        do{
            Sleep(1000);
            value = countdown(value);
            sprintf(arrayValue,"%d",value);
            gtk_label_set_label(GTK_LABEL(myLabel),arrayValue);
        } while(value > 0);
    }
    Alors le compte à rebours marche bien( j'ai vérifié avec g_print), mais le problème c'est que le label ne s'affiche qu'à la fin du décompte, quand je sors du while de ma fonction. En gros quand je fais un décompte de 10 secondes, j'ai la fenêtre Gtk qui s'affiche bien mais avec rien dedans et au bout de 10 secondes j'ai le nombre 0 qui s'affiche puisque le décompte est terminé.

    Du coup j'aimerais savoir s'il existe un moyen de rafraîchir ma fenêtre toutes les secondes ? Est-ce un problème avec Sleep ?

    Merci.

  13. #13
    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
    Citation Envoyé par JeremTer Voir le message
    Ensuite, j'affecte un signal à mon bouton :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    g_signal_connect(button,"clicked",G_CALLBACK(print_label),label);
    Où ma fonction label est comme ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    void print_label(GtkButton *button, gpointer user_data)
    {
        GtkWidget *label = user_data;
        g_print(gtk_label_get_label(GTK_LABEL(label)));
    }
    Bien-sûr ça ne fonctionne pas. J'ai compris comment faire passer une structure mais je ne sais même pas comment faire passer un simple pointeur.
    Lis la doc de g_signal_connect. Le dernier paramètre, "data", ce sont les données que tu souhaites passer à ta callback.
    Pour passer une structure, le mieux est de la passer par adresse plutôt que par valeur. En gros tu donnes l'adresse de la structure, plutôt que de demander de copier toute la structure.
    Tu passes donc juste le nom d'un pointeur pointant vers ta structure, ou l'adresse de ta structure (nom de ta variable structure, préfixée par "&", genre &ma_struct).
    Un GtkWidget, c'est just une structure (des données). Un GtkWidget *, c'est un pointeur vers ces données. Un gpointer, c'est un "pointeur vers quelque chose dont le type n'est pas défini", c'est un void *.
    Donc quand tu veux passer une structure allouée dans la pile ("struct toto ma_struct;"), alors tu dois passer l'adresse de cette structure à g_signal_connect:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    g_signal_connect(..., ..., ..., &ma_struct);
    Si c'est une structure allouée dans le tas (c'est à dire avec une fonction comme malloc, g_malloc, g_new, etc.), alors tu as un pointeur vers la structure, et tu le passes tel quel.

    Citation Envoyé par JeremTer Voir le message
    De plus, je ne comprends pas très bien le premier argument de la fonction print_label que j'ai mis car on le retrouve dans tous les callbacks que j'ai vu : GtkButton *button.
    Je ne vois ni à quoi il sert, ni ce qu'il contient car on envoie aucune données sur ce paramètre ou alors je ne le trouve pas ?
    Le premier argument d'une callback correspond à l'object donc le signal a été activé. Tu as connecté une callback au signal "clicked" d'un bouton, donc quand on clique sur le bouton, ta callback est appelée, et le premier argument est le bouton sur lequel on a cliqué.
    Si tu préfères mettre en commun du code, par exemple pour la modification de ton label, tu peux utiliser g_signal_connect_swapped au lieu de g_signal_connect. Cela indique que l'objet sur lequel tu comptes intervenir est celui passé en paramètre et non pas celui qui a généré l'action. Le premier paramète et le paramètre passé vie user_data sont alors échangés ("swapped") au moment d'appeler la callback. Dans ton cas, cela veut dire que tu t'intéresses au label, pas au boutton. g_signal_connect_swapped peut être utile si tu as plusieurs moyen de déclencher la même action par exemple.
    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)

  14. #14
    Membre à l'essai
    Homme Profil pro
    Ingénieur informatique
    Inscrit en
    Novembre 2018
    Messages
    31
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2018
    Messages : 31
    Points : 10
    Points
    10
    Par défaut
    D'accord merci de ta réponse, j'ai réussi à faire ce que je voulais maintenant.

    Cependant, aurais-tu une idée pour répondre à mon dernier post ?

    Cordialement.

  15. #15
    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
    Le problème que tu rencontres vient du fonctionnement de l’interface graphique.

    Pour faire simple le code d’une interface est une boucle while();. Elle tourne sans fin tant qu’un signal n’est pas émis.
    Puisque tu crées à l’interieur de cette boucle ta propre boucle tu bloques celle de l’ihm. De ce constat la fonction sleep(); est à proscrire dans une ihm.

    Alors y a-t-il une solution ?

    Oui bien sûr . Ouf on s’en sort bien !

    La boucle while (); de l’ihm exécute une liste de fonctions pour permettre le maintien de l’affichage et l’ecoute des interactions des widgets qui la composent. Il est possible d’inserer dans cette liste nos propres fonctions. On peut même lui demander de l’exécuter en fonction d’un intervalle de temps.

    Tu pourras utiliser à cet effet la fonction g_timeout_add (); et ses dérivées.

  16. #16
    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
    À noter que g_timeout_add ne te fournit pas de garantie de précision, donc les retards se cumulent. Si tu as un long compte à rebours et que le système est très chargé par une application (la tienne ou une autre), tu peux te retrouver avec un temps final plus long. J'ai fait un petit métronome en GTK+, dans ce cas de figure il faut ruser pour éviter que les erreurs de précision ne s'additionnent.
    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)

  17. #17
    Membre à l'essai
    Homme Profil pro
    Ingénieur informatique
    Inscrit en
    Novembre 2018
    Messages
    31
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2018
    Messages : 31
    Points : 10
    Points
    10
    Par défaut
    OK merci bien, j'ai réussi finalement avec g_timeout_add_seconds finalement et cela devrait suffire vu que mes compte à rebours ne dépassent pas 45 secondes.

  18. #18
    Membre à l'essai
    Homme Profil pro
    Ingénieur informatique
    Inscrit en
    Novembre 2018
    Messages
    31
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2018
    Messages : 31
    Points : 10
    Points
    10
    Par défaut
    Bonsoir tout le monde, j'espère ne pas trop vous déranger avec mes nombreuses questions, j'en pose le moins possible mais seulement là je suis bloqué depuis 2 jours.

    J'essaye d'améliorer mon code en transformant mon gigantesque main en fonctions pour que ce soit plus propre.

    Voilà mon simple but : afficher des données qu'une personne aura écrite pour s'inscrire.

    Pour cela je fais appel à plusieurs fonctions, mais tout d'abord voici ma structure :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    typedef struct RegistInfo{
        GtkBuilder *builder;
        char *name;
        char *mail;
        char *password;
        char *confirmPassword;
    }RegistInfo;
    C'est dans une structure de ce type que je compte ranger les informations que l'utilisateur aura saisi.

    La première fonction appelée est celle-ci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    void createAccount()
    {
        GtkWidget *windowRegister;
        GtkWidget *button;
        RegistInfo info;
        info.builder = gtk_builder_new();
        addBuilderFromGlade(info.builder,"userRegister.glade");
        button = GTK_WIDGET(gtk_builder_get_object(info.builder,"confirmRegister"));
        windowRegister = GTK_WIDGET(gtk_builder_get_object(info.builder,"windowRegister"));
        g_signal_connect(windowRegister,"destroy",G_CALLBACK(gtk_main_quit),NULL);
        g_signal_connect(button,"clicked",G_CALLBACK(getInfoToRegister),&info);
        g_object_unref(info.builder);
        gtk_widget_show(windowRegister);
    }
    Voici addBuilderFromGlade :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    int addBuilderFromGlade(GtkBuilder *builder,char *fileName)
    {
        GError *error = NULL;
        if( ! gtk_builder_add_from_file( builder, fileName, &error ) )
        {
            g_warning( "%s", error->message );// -> pointe sur membre de structure
            g_free( error );
            return EXIT_FAILURE;
        }
        return EXIT_SUCCESS;
    }
    Donc une fois que je confirme l'envoi de mon formulaire, j’appelle cette fonction en transmettant &info :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    void getInfoToRegister(GtkButton *button,RegistInfo *info)
    {
        info->name = getTextOfEntry(info->builder,"entryRegisterName");
        printRegister(info);
    }
    Et voici enfin la fonction censé afficher :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    void printRegister(RegistInfo *info)
    {
        g_print("\nNAME : %s\n",info->name);
    }
    Pour commencer, je ne le fais qu'avec un seul champ qui est name afin de gagner du temps.

    L'erreur est la suivante :
    Nom : erreurGtk.PNG
Affichages : 771
Taille : 11,4 Ko

    Est-ce que quelqu'un pourrait m'éclairer svp ?

    Merci,

    Bien cordialement.

    PS: je ne sais jamais quand est-ce qu'il faut faire des mallocs lors des initialisations de structure avec des pointeurs dedans, puis-je avoir une explication ? Merci !

  19. #19
    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
    Bonjour.

    Après une lecture très rapide je me demande si le pointeur builder est bien initialisé à la sortie de la fonction addBuilderFromGlade ();. Je pense que tu devrais plutôt passer GtkBuilder **builder.

    À réfléchir...

  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
    Pour les malloc();, tout dépend de la manière dont tu implémentes ton code. Oui, je sais, c'est presque une réponse de Normand .

    Je m'explique. Tu disposes de cette structure :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    ypedef struct RegistInfo{
        GtkBuilder *builder;
        char *name;
        char *mail;
        char *password;
        char *confirmPassword;
    }RegistInfo;
    La première allocation possible est une réservation pour une donnée du type de cette structure : Registinfo registre;. Tu remarqueras que pour l'instant je n'ai déclaré qu'une variable.

    Revenons aux fondamentaux du C. Il existe deux types d'allocation :

    1. dans la pile,
    2. dans le tas.

    Lorsque tu ouvres une accolade, le système d'exploitation réserve un espace mémoire, 1Mo par exemple. Sa taille dépend du système d'exploitation et aussi de sa configuration (on peut la changer). Lorsque l'accolade se ferme, cet espace est libéré. Cet espace est nommé la pile.

    Imaginons maintenant que j'ai dans la fonction main (); la déclaration précédente :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    int main (int argc, char **argv)
    {
      Registinfo registre;
    }
    Tant que l'accolade n'est pas fermée registre existe. Donc tant que mon programme est exécuté, registre est utilisable. Il me suffit de transmettre son adresse à mes différentes fonctions pour l'utiliser. (&registre).

    Prenons un deuxième exemple. Imaginons maintenant que registre doit être initialisé par une fonction à laquelle je ne peux pas transmettre son pointeur. Cette fonction me retournera un pointeur sur une variable de type RegistInfo.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    RegistInfo *initRegistre ()
    {
      RegistInfo *registre = malloc (sizeof (RegistInfo));
     
      return registre;
    }
    Cette fois-ci tu remarqueras l'utilisation de malloc();. Si je déclare simplement Registinfo registre; et que je retourne registre, tu auras remarqué que l'accolade se ferme. registre serait perdu. Il me faut donc allouer de l'espace en dehors de celui alloué dans les accolades (la pile). On nomme cet espace mémoire le tas.
    Puisque j'ai alloué dans le tas, il me faudra utiliser free(registre); lorsque registre ne me sera plus utile. Sinon il y aura une fuite mémoire.


    Maintenant que j'ai posé les bases, dans la structure Registinfo il y a aussi des pointeurs. Soit tu utilises malloc(); pour les alloués, et donc il faudra un free(); avec lors de la destruction de registre, soit tu peux utiliser une déclaration locale, c'est à dire dans la pile. Tu remarqueras pour finir que la déclaration de la structure utilise elle aussi des accolades. Donc toutes les données à l'intérieur existent tant que registre existe .

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

Discussions similaires

  1. [FAQ] Comment utiliser glade avec GtkBuilder ?
    Par Rachel dans le forum Contribuez
    Réponses: 2
    Dernier message: 01/11/2012, 12h55
  2. utiliser glade avec python sous windows
    Par sakura.sou dans le forum EDI/RAD
    Réponses: 1
    Dernier message: 25/07/2009, 09h31
  3. Réponses: 5
    Dernier message: 17/05/2007, 01h19
  4. Faut-il combiner Spring avec Struts ou utiliser Spring MVC ?
    Par micanti dans le forum Frameworks Web
    Réponses: 3
    Dernier message: 23/04/2007, 16h31
  5. [RegEx] Que faut-il utiliser avec l'UFT-8 : Regex ou POSIX ?
    Par Tchinkatchuk dans le forum Langage
    Réponses: 2
    Dernier message: 07/11/2006, 17h13

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