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 :

[GTK+ 3.10] Affichage dynamique


Sujet :

GTK+ avec C & C++

  1. #1
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2011
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2011
    Messages : 25
    Points : 18
    Points
    18
    Par défaut [GTK+ 3.10] Affichage dynamique
    Bonjour,

    Je suis entrain de faire un programme permettant l'exécution d'automates cellulaires à deux dimensions, et je fait toute la partie graphique avec GTK+.

    J'ai un souci pour l'affichage de l'automate.

    Pour l'afficher j'ai fait une image que je créé initialement grâce à un pixbuf, je met ensuite l'image dans la fenêtre. À chaque étapes de l'automate je détruit l'image qui est affiché, et j'en créé une nouvelle à partir d'un pixbuf correspondant au nouvel état de l'automate.
    Le problème c'est que ça ne marche pas ! Rien n'est mis à jours, et si je change de fenêtre, puis je reviens sur mon application, la fenêtre est devenue complètement vide, plus rien n'est affiché (les menus, les boutons,...).

    Comme il semble que ce ne soit pas la bonne méthode j'ai cherché un autre moyen de parvenir à mes fins. J'ai donc trouvé les gtkDrawingArea. Le problème c'est que je n'y comprend pas grand chose. J'ai trouvé deux exemples (ici et ) pour essayé d'y voir un peu plus claire, mais que je compile gcc me dit que gktwidget ou gtkdrawingarea n'ont pas d'attributs window ou allocation.

    Je ne sais vraiment pas comment m'y prendre, donc si quelqu'un veut bien éclairer ma lanterne je lui en serais très reconnaissant.

    Cordialement,
    Phantom

    PS : je ne sais pas si ça change quelque chose, mais je suis sous Ubuntu 14.04, et j'utilise la version 3.10 de GTK+.

  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.

    Pour pouvoir t'apporter un début de réponse il nous faut le code incriminé. Te répondre sans est pour nous impossible .

  3. #3
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2011
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2011
    Messages : 25
    Points : 18
    Points
    18
    Par défaut
    La fonction qui lance l'automate, elle est appelé quand on clique sur un bouton. J'ai essayé d'utiliser les threads pour voir si ça changé quelque chose, mais non.
    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
     
    // callback function to play the automaton
    void play (GtkWidget* window, gpointer data) {
    	GtkWidget* image;
    	pthread_t thread;
     
    	g_signal_handler_disconnect (window, proc.handP);
    	proc.handP=g_signal_connect (G_OBJECT(window), "clicked", G_CALLBACK(pause_auto), NULL);
    //	image=gtk_image_new_from_stock (GTK_STOCK_MEDIA_PAUSE, GTK_ICON_SIZE_BUTTON);
    	image=gtk_image_new_from_icon_name ("media-playback-pause", GTK_ICON_SIZE_BUTTON);
    	gtk_button_set_image (GTK_BUTTON(window), image);
     
    	proc.holdOn=1;
    	proc.stop=0;
    	while (proc.holdOn==1) {
    		//timer
    		if (proc.holdOn==1) {
    			MPI_Bcast (&(proc.stop), 1, MPI_INT, 0, MPI_COMM_WORLD);
    			recv_grid ();
    /*int i;
    for (i=0 ; i<proc.width ; i++) {
    	printf ("%d ", proc.grid[i]);
    }
    printf ("\n");*/
    			while (pthread_create (&(thread), NULL, print_grid, NULL)!=0) {
    				perror ("pthread_create");
    			}
    			pthread_join (thread, NULL);
    	gtk_widget_show_all (scrolledWindow);
    //			print_grid ();
    sleep (1);
    		}
    	}
    }
    La fonction qui est censé afficher la grille dans la fenêtre.
    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
     
    // to display the grid
    void* print_grid (void* arg) {
    	GdkPixbuf* pixbuf;
    	GtkWidget* image;
    	int i, j, zi, zj;
    	GList* list;
     
     
    for (i=0 ; i<proc.width ; i++) {
    	printf ("%d ", proc.grid[i]);
    }
    printf ("\ndans print_grid\n");
    	list=gtk_container_get_children (GTK_CONTAINER(scrolledWindow));
    	if (list!=NULL) {
    		gtk_container_remove (GTK_CONTAINER(scrolledWindow), (GtkWidget*)list->data);
    	}
     
    	pixbuf=gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, proc.width*proc.zoom, proc.height*proc.zoom);
     
    	for (i=0 ; i<proc.height ; i++) {
    		for (j=0 ; j<proc.width ; j++) {
    			if (proc.grid[i*proc.width+j]==0) {
    				for (zi=0 ; zi<proc.zoom ; zi++) {
    					for (zj=0 ; zj<proc.zoom ; zj++) {
    						put_pixel (pixbuf, j*proc.zoom+zj, i*proc.zoom+zi, 255, 255, 255);
    					}
    				}
    			}
    			else {
    				for (zi=0 ; zi<proc.zoom ; zi++) {
    					for (zj=0 ; zj<proc.zoom ; zj++) {
    						put_pixel (pixbuf, j*proc.zoom+zj, i*proc.zoom+zi, 0, 0, 0);
    					}
    				}
    			}
    		}
    	}
     
    	image=gtk_image_new_from_pixbuf (pixbuf);
    	gtk_container_add (GTK_CONTAINER(scrolledWindow), image);
    	gtk_widget_show_all (scrolledWindow);
     
    	return NULL;
    }
    La fonction put_pixel est une fonction trouvé sur un tutoriel sur les pixbuf (je ne sais plus où).

    Dans la seconde fonction plutôt que de supprimer l'ancienne image j'ai essayé de la modifier par la fonction gtk_image_set_from_pixbuf, mais le résultat est toujours le même.

    Enfin, comme c'est une application répartie grâce à la bibliothèque MPI, le processus chargé de l'affichage récupère la grille dans la fonction recv_grid. Je ne pense pas que le problème vienne de là car quand j'affiche des choses dans le terminal à chaque étapes, tout se passe bien.

    J'espère que ça vous aidera à m'aider.

  4. #4
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    26
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2008
    Messages : 26
    Points : 28
    Points
    28
    Par défaut
    Phantomlibre,

    L'idéal serait même de poster le code complet, pour qu'on l'essayer et le corriger facilement, mais ce n'est peut-être pas possible... ?

    Sinon, mes idées : GTK+ utilise un système de boucle principale nommé "g_main_loop". Tu la lances en principe une fois dans la fonction "main()" -> "gtk_main ();"
    Le redessinage des widgets, et à plus forte raison des autres éléments graphiques, n'est effectué qu'à chaque fois que cette boucle s'exécute.

    Si tu boucles via ta propre logique, par exemple avec ton propre timer, GTK+ va lui donner la main et se "pauser" en attendant que ce soit fini ; et donc tu arrives dans l'état "blanc/gelé" que tu as observé.

    Une solution serait d'appeler à chaque fois :
    ce qui va faire avancer la boucle, juste après avoir demandé explicitement à GTK+ de redessiner ton widget :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    gtk_widget_queue_draw (widget);
    Voici l'ensemble si tu veux ne reprendre ton timer que quand GTK+ a traité tous ses événements (plus fluide, mais rend les délais imprédictibles) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    gtk_widget_queue_draw (widget);
    while (gtk_events_pending ())
       gtk_main_iteration ();

  5. #5
    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
    Utiliser des threads en dehors de la boucle principale Gtk+ pour modifier des widgets est source à problème. Commence par utiliser une simple boucle pour afficher "normalement" les unes à la suite des autres tes images.

    Ensuite une petite question : scrolledwindow est-elle une variable globale ?

    Petite remarque. Tu devrais renommer GtkWidget *window dans ta fonction callback en GtkWidget *button. Ca évitera des confusions...

    Dernière petite question : de quoi est composée la fonction pause_auto(); ?

  6. #6
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2011
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2011
    Messages : 25
    Points : 18
    Points
    18
    Par défaut
    \o/ Ça marche !!!

    Merci Tarnyko !

    Citation Envoyé par gerald3d Voir le message
    Utiliser des threads en dehors de la boucle principale Gtk+ pour modifier des widgets est source à problème. Commence par utiliser une simple boucle pour afficher "normalement" les unes à la suite des autres tes images.
    Enlevé.

    Citation Envoyé par gerald3d Voir le message
    Ensuite une petite question : scrolledwindow est-elle une variable globale ?
    Oui tout à fait.


    Citation Envoyé par gerald3d Voir le message
    Petite remarque. Tu devrais renommer GtkWidget *window dans ta fonction callback en GtkWidget *button. Ca évitera des confusions...
    C'était prévu dans le nettoyage du code une fois que tout marchera.


    Citation Envoyé par gerald3d Voir le message
    Dernière petite question : de quoi est composée la fonction pause_auto(); ?
    Elle déconnecte le signal qu'il y a sur la bouton play/pause, elle remet un signal qui appel la fonction play, elle change l’icône, et elle met la variable holdOn à 0 pour sortir de la boucle qui est dans play.


    Merci à tout les deux.


    PS : je laisse le sujet non résolut quelque temps au cas où vous souhaiteriez rajouter quelque chose.

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

Discussions similaires

  1. affichage dynamique gtk
    Par bilel016 dans le forum GTK+ avec C & C++
    Réponses: 1
    Dernier message: 17/04/2007, 08h53
  2. Problème d'affichage dynamique d'une liste
    Par bor1s dans le forum ASP
    Réponses: 2
    Dernier message: 18/11/2005, 16h18
  3. Réponses: 1
    Dernier message: 08/07/2005, 02h46
  4. [VB.NET] - affichage dynamique dans un tableau
    Par karibouxe dans le forum ASP.NET
    Réponses: 8
    Dernier message: 20/06/2005, 15h07
  5. affichage dynamique en fonction des données en base
    Par jengo dans le forum Bases de données
    Réponses: 1
    Dernier message: 28/10/2004, 10h22

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