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 :

problème compilation gtk3


Sujet :

GTK+

  1. #1
    Futur Membre du Club
    Homme Profil pro
    Inscrit en
    Mars 2012
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2012
    Messages : 10
    Points : 7
    Points
    7
    Par défaut problème compilation gtk3
    bonjour,

    Suite à une problème dans la création d'un gui (un texte dans un bouton qui doit être modifié), j'ai essayé de reproduire +/- la même situation avec un petit programme que je vous met ci-après.

    Après avoir poussé sur le bouton "start" le texte et la couleur devrait se modifier toute les seconde dans le bouton "Read".

    la compilation du programme se fait avec la commande suivante

    gcc -Wall boutonTest.c `pkg-config --cflags --libs gtk+-3.0`

    J'ai toutes sortes de comportement avec ce petit programme, quelqu'un pourrait-il m'aider ?

    je suis actuellemnt sur slackware 14 , mais le problème est identique avec mint 13

    D'avance merci

    #include <stdlib.h>
    #include <stdbool.h>
    #include <stdio.h>
    #include <string.h>
    #include "gtk/gtk.h"
    #include <pthread.h>

    static GtkWidget *window;
    static GtkWidget *grid;
    static GtkWidget *buttonRead;
    static GtkWidget *buttonStart;

    static GtkCssProvider *provider;
    static GdkDisplay *display;
    static GdkScreen *screen;

    static int iret1 = 0;
    static pthread_t thread1;

    static int nb = 0;

    static gboolean window_delete_event( GtkWidget *widget, GdkEvent *event, gpointer data ){
    gtk_widget_destroy(window);
    gtk_main_quit ();
    return TRUE;
    }

    void testRun(){
    if (strcmp( gtk_button_get_label(GTK_BUTTON(buttonRead)),"Read") == 0){
    gtk_button_set_label(GTK_BUTTON(buttonRead), "Write");
    g_print(" new label is %s\n",gtk_button_get_label(GTK_BUTTON(buttonRead)));
    provider = gtk_css_provider_new ();
    gtk_style_context_add_provider_for_screen (screen, GTK_STYLE_PROVIDER (provider), GTK_STYLE_PROVIDER_PRIORITY_USER);
    gtk_css_provider_load_from_data (GTK_CSS_PROVIDER (provider),
    " GtkButton#buttonRead {\n"
    " color: blue;\n"
    "}\n", -1, NULL);

    g_object_unref (provider);
    }
    else {
    gtk_button_set_label(GTK_BUTTON(buttonRead), "Read");
    g_print(" new label is %s\n",gtk_button_get_label(GTK_BUTTON(buttonRead)));
    provider = gtk_css_provider_new ();
    gtk_style_context_add_provider_for_screen (screen, GTK_STYLE_PROVIDER (provider), GTK_STYLE_PROVIDER_PRIORITY_USER);
    gtk_css_provider_load_from_data (GTK_CSS_PROVIDER (provider),
    " GtkButton#buttonRead {\n"
    " color: red;\n"
    "}\n", -1, NULL);

    g_object_unref (provider);
    }
    }

    static void *threadRun( ){
    while(1){
    sleep(1);
    nb +=1;
    g_print(" nb is %d\n", nb);
    testRun();
    }
    return NULL;
    }


    static void callbackButtonStart( GtkWidget *widget, gpointer *data ){
    iret1 = pthread_create( &thread1, NULL, threadRun, (void*) NULL);
    }

    static void initLayout(){
    window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
    gtk_window_maximize (GTK_WINDOW (window));
    gtk_window_set_title (GTK_WINDOW (window), "Test");
    gtk_container_set_border_width (GTK_CONTAINER (window), 20);
    g_signal_connect (window, "delete-event", G_CALLBACK (window_delete_event), NULL);

    grid = gtk_grid_new ();
    gtk_grid_set_column_spacing (GTK_GRID(grid),10);
    gtk_grid_set_row_spacing (GTK_GRID(grid),10);
    gtk_container_add (GTK_CONTAINER (window), grid);

    buttonRead = gtk_button_new_with_label ("Read");
    gtk_widget_set_name (GTK_WIDGET(buttonRead), "buttonRead");
    gtk_widget_set_size_request(buttonRead, 90,50);
    gtk_grid_attach(GTK_GRID(grid),buttonRead,1,0,1,1);

    buttonStart = gtk_button_new_with_label ("Start");
    gtk_widget_set_size_request(buttonStart, 90,50);
    gtk_grid_attach(GTK_GRID(grid),buttonStart,2,0,1,1);
    g_signal_connect (buttonStart, "clicked", G_CALLBACK (callbackButtonStart), "Read");

    gtk_widget_show_all(window);
    }

    int main( int argc, char *argv[] ) {
    gtk_init (&argc, &argv);
    initLayout();
    display = gdk_display_get_default ();
    screen = gdk_display_get_default_screen (display);

    printf("screen width is %d\n", gdk_screen_get_width(screen));
    printf("screen height is %d\n\n", gdk_screen_get_height(screen));

    gtk_main();
    return 0;
    }

  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
    Bonjour,

    1. le signal delete-event sert quand on doit changer le comportement de fermeture de la fenêtre (ex: pour afficher une boite de dialogue de confirmation). S'il n'y a rien à changer, c'est le signal "destroy" auquel il faut se connecter
    2. comme la plupart des toolkits, GTK n'est pas thread-safe
    3. selon ta version de la GLib, il faut peut être appeler g_thread_init avant de lancer ton programme. Ce n'est plus nécessaire depuis GLib 2.32, et peut être que ce n'est pas du tout nécessaire vu que tu utilises les pthreads directement, mais j'ai un doute.
    4. dans tous les cas, un exemple aussi simple ne devrait pas utiliser des threads, mais g_timeout_add ou g_timeout_add_seconds. C'est aussi faisable avec des threads, mais le thread doit servir uniquement à incrémenter la valeur, toute la partie graphique qui change l'état du bouton doit se faire dans le thread principal.
    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
    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
    Voilà un 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
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
     
    #include <stdlib.h>
    #include <stdbool.h>
    #include <stdio.h>
    #include <string.h>
    #include "gtk/gtk.h"
    #include <pthread.h>
     
    static GtkWidget *window;
    static GtkWidget *grid;
    static GtkWidget *buttonRead;
    static GtkWidget *buttonStart;
     
    static GtkCssProvider *provider;
    static GdkDisplay *display;
    static GdkScreen *screen;
     
    static int iret1 = 0;
    static pthread_t thread1;
     
    static int nb = 0;
     
    static void on_destroy (GtkWidget *widget, gpointer data){
    	gtk_main_quit ();
    }
     
    gboolean on_counter_changed (gpointer user_data)
    {
    	if (nb % 2 == 0)
    		gtk_button_set_label(GTK_BUTTON(buttonRead), "Read");
    	else
    		gtk_button_set_label(GTK_BUTTON(buttonRead), "Write");
     
    	g_print(" new label is %s\n", gtk_button_get_label(GTK_BUTTON(buttonRead)));
    	provider = gtk_css_provider_new ();
    	gtk_style_context_add_provider_for_screen (screen, GTK_STYLE_PROVIDER (provider), GTK_STYLE_PROVIDER_PRIORITY_USER);
    	char *css = g_strdup_printf (" GtkButton#buttonRead {\n"
    			" color: %s;\n"
    			"}\n",
    			nb % 2 ? "blue" : "red");
     
    	gtk_css_provider_load_from_data (GTK_CSS_PROVIDER (provider), css, -1, NULL);
    	g_object_unref (provider);
    	g_free (css);
    	return TRUE;
    }
     
    static void *threadRun( )
    {
    	while (1)
    	{
    		sleep(1);
    		nb +=1;
    		g_print(" nb is %d\n", nb);
    	}
    	return NULL;
    }
     
     
    static void callbackButtonStart( GtkWidget *widget, gpointer *data ){
    	g_timeout_add_seconds (1, on_counter_changed, NULL);
    	iret1 = pthread_create( &thread1, NULL, threadRun, (void*) NULL);
    }
     
    static void initLayout(){
    	window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
    	gtk_window_maximize (GTK_WINDOW (window));
    	gtk_window_set_title (GTK_WINDOW (window), "Test");
    	gtk_container_set_border_width (GTK_CONTAINER (window), 20);
    	g_signal_connect (window, "destroy", G_CALLBACK (on_destroy), NULL);
     
    	grid = gtk_grid_new ();
    	gtk_grid_set_column_spacing (GTK_GRID(grid),10);
    	gtk_grid_set_row_spacing (GTK_GRID(grid),10);
    	gtk_container_add (GTK_CONTAINER (window), grid);
     
    	buttonRead = gtk_button_new_with_label ("Read");
    	gtk_widget_set_name (GTK_WIDGET(buttonRead), "buttonRead");
    	gtk_widget_set_size_request(buttonRead, 90,50);
    	gtk_grid_attach(GTK_GRID(grid),buttonRead,1,0,1,1);
     
    	buttonStart = gtk_button_new_with_label ("Start");
    	gtk_widget_set_size_request(buttonStart, 90,50);
    	gtk_grid_attach(GTK_GRID(grid),buttonStart,2,0,1,1);
    	g_signal_connect (buttonStart, "clicked", G_CALLBACK (callbackButtonStart), "Read");
     
    	gtk_widget_show_all(window);
    }
     
    int main( int argc, char *argv[] ) {
    	gtk_init (&argc, &argv);
    	initLayout();
    	display = gdk_display_get_default ();
    	screen = gdk_display_get_default_screen (display);
     
    	printf("screen width is %d\n", gdk_screen_get_width(screen));
    	printf("screen height is %d\n\n", gdk_screen_get_height(screen));
     
    	gtk_main();
    	return 0;
    }
    Pas encore idéal, mais ça donne une idée. J'ai laissé le thread pour montrer comment s'agencer avec lui, mais en fait il n'est pas du tout nécessaire, incrémenter le compteur dans la callback du timer ferait aussi bien l'affaire. Là tu fais un sleep(1), mais si le timing n'est pas connu, je pense qu'il faudrait déclarer un nouveau signal, et à partit du thread, émettre ce signal, pour que GTK puisse le traiter dans la boucle principale.
    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)

  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
    J'ajoute aussi que les variables globales, c'est sale.
    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
    Futur Membre du Club
    Homme Profil pro
    Inscrit en
    Mars 2012
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2012
    Messages : 10
    Points : 7
    Points
    7
    Par défaut
    merci pour l'info

    j'ignorais l'utilisation de g_timeout_add, je supposais bien que les threads étaient +/- resposables du problème, mais pas à ce point!!

    Existe-il une doc ou un livre qui traite de ce sujet, spécialement pour gtk3 ??

  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
    Citation Envoyé par mikedew Voir le message
    Existe-il une doc ou un livre qui traite de ce sujet, spécialement pour gtk3 ??
    Livre, c'est sûr que non, mais c'était le même problème sur GTK2. En fait, c'était possible de contourner la limitation avec gdk_threads_enter/gdk_threads_leave:
    http://blogs.operationaldynamics.com...read-awareness
    http://developer.gnome.org/gtk-faq/stable/x481.html

    Mais en fait à l'usage cela pose des problèmes sur plein de plate-formes, et le support de l'accès aux composants graphiques par plusieurs threads a tout bonnement été abandonné dans GTK 3.6:
    https://mail.gnome.org/archives/comm.../msg07237.html

    La méthode à utiliser est donc celle que j'ai indiqué dans mon exemple: utiliser les fonctions de la pompe à événement GTK pour déclencher des callbacks, et manipuler l'interface à partir de ces callbacks, qui seront exécutées à partir du thread principal.

    Si des threads sont obligatoires (worker thread, à utiliser pour une longue opération), alors ces threads ne font que mettre à jour des structures ou variables à toi, et envoyer des événements dans la pompe à événements. Ces événements seront ensuite traités par GTK dans le thread principal.

    La version que j'ai écrite est assez simple pour l'illustrer: le thread ne fait qu'incrémenter ton compteur. C'est ensuite quand GTK reçoit un événement (j'ai utilisé ici un timer d'une seconde) que la callback correspondante est appelée, et va lire le contenu du compteur pour mettre à jour l'affichage. Et ça c'est GTK qui le fait comme un grand dans le thread principal.

    Pour exécuter des actions longues, tu as aussi la possibilité de fractionner ton traitement. Il est ainsi possible de faire du lazy loading:
    http://web.archive.org/web/200803210.../lazy-loading/

    g_idle_add est une fonction très utile, qui peut lancer une callback quand il n'y a rien d'autre à faire.
    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
    Futur Membre du Club
    Homme Profil pro
    Inscrit en
    Mars 2012
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2012
    Messages : 10
    Points : 7
    Points
    7
    Par défaut
    Vraiment super comme aide

    Encore merci

Discussions similaires

  1. [VB5] Problème compilation, ocx manquants
    Par rastali dans le forum VB 6 et antérieur
    Réponses: 2
    Dernier message: 10/10/2005, 14h39
  2. [Kylix] Problème de compilation
    Par rabbi_jaccob dans le forum EDI
    Réponses: 3
    Dernier message: 25/07/2005, 23h36
  3. Problème compilation (toolkit Maximum Entropy)
    Par yannick_frere dans le forum MFC
    Réponses: 4
    Dernier message: 07/03/2005, 09h47
  4. Problème compilation Version 8.0.1 sous Debian Sarge
    Par LIndien dans le forum PostgreSQL
    Réponses: 1
    Dernier message: 04/02/2005, 21h38
  5. [Kylix] problème compilation kylix3 avec redhat 9.0
    Par madininaoursa dans le forum EDI
    Réponses: 1
    Dernier message: 02/07/2003, 16h21

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