Bonjour
Je cherche à pouvoir colorier une combo box : le fond et/ou le texte. La couleur d'une même entrée de cette liste déroulante pouvant changer au cours de l'exécution du programme, elle n'est donc pas figée.
Bonjour
Je cherche à pouvoir colorier une combo box : le fond et/ou le texte. La couleur d'une même entrée de cette liste déroulante pouvant changer au cours de l'exécution du programme, elle n'est donc pas figée.
Modérateur Mageia/Mandriva Linux
Amicalement VOOotre
Troumad Alias Bernard SIAUD à découvrir sur http://troumad.org
Mes tutoriels : xrandr, algorigramme et C, xml et gtk...
Je suis arrivé à faire quelque chose de pas génail, mais quelque chose tout de même. Je colorie toutes les entrées du menu. Ce n'est pas génail, mais c'est déjà ça :où GTK_CELL_LAYOUT(((GtkWidget ***)param)[M_CE_ARMES][k] est le GtkCellRenderer déclaré pour ce menu avec
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10 if (arme_OK==1) { g_object_set(GTK_CELL_LAYOUT(((GtkWidget ***)param)[M_CE_ARMES][k]), "cell_background", 0, NULL); } else { g_object_set(GTK_CELL_LAYOUT(((GtkWidget ***)param)[M_CE_ARMES][k]), "cell_background", "#FF0000", NULL); } gtk_widget_hide_all(((GtkWidget ***)param)[M_PC_ARMES][k]); gtk_widget_show_all(((GtkWidget ***)param)[M_PC_ARMES][k]);nb : pour la lisibilité de mon code, j'ai plein de constante prédéfinie et j'en ai rajouté plus de 30 constantes depuis http://www.developpez.net/forums/d10...k_spin_button/ !
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 p_cell = gtk_cell_renderer_text_new (); gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (((GtkWidget ***)param)[M_PC_CLASSE+offset][((unsigned short **)param)[M_NB_CLASSE+offset][0]]),p_cell, FALSE); gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (((GtkWidget ***)param)[M_PC_CLASSE+offset][((unsigned short **)param)[M_NB_CLASSE+offset][0]]),p_cell, "text", 0,NULL);
Ceci vous semble peut-être grossier, mais c'est que je travaille sans variable globale![]()
Modérateur Mageia/Mandriva Linux
Amicalement VOOotre
Troumad Alias Bernard SIAUD à découvrir sur http://troumad.org
Mes tutoriels : xrandr, algorigramme et C, xml et gtk...
troumad, même sans variable globale, tu n'as en général pas besoin utiliser des tableaux à 2 dimensions de pointeurs triples... Une structure bien élaborée évite en général d'avoir à se flageller de cette manière. Pour accéder à une donnée on définit en général des accesseurs (fonctions get_* et set_*) qui permettent de récupérer facilement la donnée à travailler... Imagine que tu veux changer quelque chose de ta disposition qui affecte la manière dont tes données sont rangées, tu te vois retrouver toutes les occurrences de ton accès à ta donnée pour la modifier ? Le risque d'erreur est énorme.
Il faut aussi au maximum éviter la duplication de code.
En récrivant ton exemple ainsi :
Tu évites la duplication de ta ligne de code (du fonctionnel) et tu la remplace par de la donnée. Cela facilite en général la vie dans bien des cas. Si tu implémentes un "getter" pour récupérer facilement le widget à manipuler, tu améliores encore la lisibilité de ton code.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7 const gchar *color = "#FF0000"; if (arme_OK == 1) color = NULL; g_object_set (GTK_CELL_LAYOUT(((GtkWidget ***)param)[M_CE_ARMES][k]), "cell_background", color, NULL);
Avec un getter, cela devient vite plus clair (je te donne un exemple là, à toi de l'adapter, cela ne compilera clairement pas en l'état). Parce que bon, des pointeurs de tableaux de pointeur etc. on en a vite marre en C. Pour éviter cela, on définit des types intermédiaires avec typedef, on fait des structures de données bien ficelées où on peut retrouver facilement ses données, et on évite de manipuler plus compliqué qu'un pointeur double... J'ai 11 ans de C/C++ dans les pattes, je t'assure qu'on est pas maso quand il n'y en a pas besoin
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 GtkCellLayout * gui_get_cell_layout (mystruct *param, guint row, guint col) { g_assert (param != NULL); g_return_val_if_fail (row < MAX_ROW); g_return_val_if_fail (col < MAX_COL); return GTK_CELL_LAYOUT(((GtkWidget ***)param)[row][col]); } [...] const gchar *color = "#FF0000"; if (arme_OK == 1) color = NULL; g_object_set (gui_get_cell_layout (param, M_CE_ARMES, k), "cell_background", 0, NULL);
Je te conseille aussi de te pencher sur GtkBuilder pour l'accès à tes widgets. Parce que là j'ai du mal à voir quelle arborescence de widgets justifierait la complexité de ce que tu fais.
J'ai utilisé ta première remarque.
Par contre, je ne peux pas utiliser ta seconde remarque ! Je m'explique par la suite.
Ce n'est pas une arborescence de widget...
C'est un tableau de pointeurs où chaque entrée peut être de nature différente. Certaines entrées peuvent être un tableau d'une série de caractéristiques qui doivent être groupées pour la compréhension => ces entrées sont des tableaux 1D et comme, on travaille avec des pointeurs sur des Widget, ça fait obligatoirement *** , mais le troisième * n'est là que pour la décoration.
Le premier * : le gpointeur du passage de paramètres
Le second * : l'item dans mon tableau
Le troisième * : un GTK_WIDGET est un pointeur sur un GtkWidget
Exemple : ((GtkWidget ***)param)[M_ENTREE][DEXTERITE]
J'ai d'autres natures d'entrées : ((unsigned short **)param)[M_NV_CLASSE][k] => un tableau d'entier par exemple. Et tous ces tableaux ont des tailles variables au cours de l'exécution du programme.
Pour la compréhension de la structure, vous pouvez regarder l'interface qui est associée à cette entrée, elle est à la page 6 de ce document : http://troumad.org/OOo/Mode_d_emploi.odt
J'ai un tableau de 9 éléments pour les caractéristiques (Force...) de la première colonne. Un autre de 8 éléments pour les compétences de voleur.
J'ai un tableau pour les Classes (Guerrier...), sachant que le nombre est à priori indéfini. Il est est de même pour les PDV, pour les compétences et les armes.
nb : j'aimerai en fait changer la couleur d'un seul item de mon combo box !
Modérateur Mageia/Mandriva Linux
Amicalement VOOotre
Troumad Alias Bernard SIAUD à découvrir sur http://troumad.org
Mes tutoriels : xrandr, algorigramme et C, xml et gtk...
Salut.
Au vu de ton document ooo l'utilisation de Glade me semble être une nécessité. Tu y gagnerais une grande souplesse de programmation et aussi une rapidité de modification non négligeable.
Pour les caractéristiques de tes personnages si certains combos sont fixes tu n'es pas obligé d'utiliser des tableaux. Il te suffit de lire la valeur sélectionnée dans le combo. En d'autres termes ton interface est une mémorisation des réglages de l'utilisateur.
Sans avoir lu très précisément tes différents posts l'utilisation de tableau me fait toujours peur. Surtout si certains d'entre eux sont à dimension indéfinie comme tu l'écris. L'utilisation ici des listes chaînées me semble plus appropriée. Ou bien les GArray.
Utilisation de Glade avec Gtk+
Code::Blocks et Gtk+ sous Windows
Programmation orientée objet avec Gtk+ v3
- N'oubliez pas de consulter les FAQ Gtk et les cours et tutoriels Gtk
@Troumad:
à quoi ressemble ta structure de données associée à un personnage ?
Il est vrai que les listes chaînées pourraient être utilisées. J'utilise la fonction realloc pour éviter d'alourdir encore plus la manipulation des données !
Pour la structure d'un personnage, passons par les constantes qui vont avec :
#define M_MEMO 0 => adresse des informations du père
#define M_CARACT 1 => les 6+1+2 caractéristiques majeurs (mémorisation du dernier état)
#define M_ENTREE 2 => spin sur les caractéristiques précédentes
#define M_FENETRE 3 => pointeur sur la fenêtre mère
#define M_PERE 4 => communication avec le père
#define M_VERSION 5 => combo version : 3 états
#define M_RACE 6 => combo race : 8é tats
#define M_SEXE 7 => combo sexe : 2 états
#define M_NV_CLASSE 8 => tableau de M_NB_CLASSE spin
#define M_NB_CLASSE 9 => nombre de classe choisie (indéfini >0)
#define M_HB_CLASSE 10 => tableau de M_NB_CLASSE Vbox contenant les M_NB_CLASSE spin et M_NB_CLASSE combo
#define M_VB_CLASSE 11 => VBox contenants les HBox
#define M_PM_CLASSE 12 =>modèle des combo
#define M_PC_CLASSE 13 => tableau de M_NB_CLASSE de combo
#define M_NV_ARMES 14 => Pareil pour classe et armes + la fin
#define M_NB_ARMES 15
#define M_HB_ARMES 16
#define M_VB_ARMES 17
#define M_PM_ARMES 18
#define M_PC_ARMES 19
#define M_LA_ARMES 32 => pointeur sur un message qui dépend du nombre d'arme
#define M_CE_ARMES 33 => tableau de M_NB_CLASSE de cell pour les combo
#define M_NV_COMP 20 => comme arme sur la fin
#define M_NB_COMP 21
#define M_HB_COMP 22
#define M_VB_COMP 23
#define M_PM_COMP 24
#define M_PC_COMP 25
#define M_LA_COMP 31 => pointeur sur un message pour les compétences générales
#define M_NV_PDV 26 => Comme les armes, sauf que cette fois, pas besoin d'une boite horizontale pour forcer l'alignement horizontal
#define M_NB_PDV 27
#define M_VB_PDV 28
#define M_CA_VOL 29 => tableaux des 8 caractéristiques de voleurs
#define M_LA_VOL 30 => message sur la répartition des caractériques
Modérateur Mageia/Mandriva Linux
Amicalement VOOotre
Troumad Alias Bernard SIAUD à découvrir sur http://troumad.org
Mes tutoriels : xrandr, algorigramme et C, xml et gtk...
Je vois juste des valeurs là, pas des structures de données. Tu n'as pas une structure "Character" ou "Personnage" ?
Les valeurs que tu donnes semblent être des identifiants associés à tes widgets. Créer ton interface avec Glade et accéder à tes widgets via GtkBuilder te simplifierait grandement la tâche...
Si tu n'es pas tenté par GtkBuilder, plutôt qu'avoir des identifiants pour tes items, crée une structure représentant ton interface graphique, et te permette de centraliser les accès à tes widgets...
J'ai répondu à la structure de mes données ! Je n'ai pas de structure pour mes personnages. Juste des tableaux. Comme je les traite les uns après les autres, j'ai le tableaux caractéristiques, le tableaux des armes, celui des compétences, celui des PDV...
L'info que j'ai passé sont les les entrée du tableau passé aux fonction CALLBACK.
Modérateur Mageia/Mandriva Linux
Amicalement VOOotre
Troumad Alias Bernard SIAUD à découvrir sur http://troumad.org
Mes tutoriels : xrandr, algorigramme et C, xml et gtk...
Dans ce cas, c'est la déclaration de tes tableaux qui serait intéressante.
Quels tableaux ? Il y en a tellement !
J'ai de la peine à imaginer plus simple avec des structures ! À la place de mes tableaux, on aurait une structure, donc à la place du numéro dans le tableau , on aurait un champ d'un structure. Comme mon numéro, je l'ai changé en constante, pour moi, c'est pareil !
Modérateur Mageia/Mandriva Linux
Amicalement VOOotre
Troumad Alias Bernard SIAUD à découvrir sur http://troumad.org
Mes tutoriels : xrandr, algorigramme et C, xml et gtk...
Extrait de ton code que tu as publié sur un autre fil de discussion:
Hé bien je t'assure qu'on peut faire bien plus lisible. Ne serait-ce qu'en évitant les casts à gogo, en passant par des variables locales, en utilisant des types énumérés, en séparant le modèle (tes structures de données) de la vue (tes widgets), en utilisant des tableaux dynamiques plutôt que des realloc, etc. Mais surtout en t'orientant vers de la programmation orienté objet où les données qui ont une lien logique sont réunies au sein d'une même structure de données.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10 ((GtkWidget ***)param)[M_NV_CLASSE+offset]=(GtkWidget **)realloc(((GtkWidget ***)param)[M_NV_CLASSE+offset],((unsigned short **)param)[M_NB_CLASSE+offset][1]*sizeof(GtkWidget *)); ((GtkWidget ***)param)[M_PC_CLASSE+offset]=(GtkWidget **)realloc(((GtkWidget ***)param)[M_PC_CLASSE+offset],((unsigned short **)param)[M_NB_CLASSE+offset][1]*sizeof(GtkWidget *)); ((GtkWidget ***)param)[M_HB_CLASSE+offset]=(GtkWidget **)realloc(((GtkWidget ***)param)[M_HB_CLASSE+offset],((unsigned short **)param)[M_NB_CLASSE+offset][1]*sizeof(GtkWidget *)); ((GtkWidget ***)param)[M_NV_CLASSE+offset][((unsigned short **)param)[M_NB_CLASSE+offset][0]]=gtk_spin_button_new_with_range(offset==12?1:0, offset==6?3:99,1); /* premier cas : compétence, second : armes */ ((GtkWidget ***)param)[M_PC_CLASSE+offset][((unsigned short **)param)[M_NB_CLASSE+offset][0]]=gtk_combo_box_new_with_model (GTK_TREE_MODEL (((GtkListStore **)param)[12+offset])); ((GtkWidget ***)param)[M_HB_CLASSE+offset][((unsigned short **)param)[M_NB_CLASSE+offset][0]] = gtk_hbox_new(FALSE, 6); /* FALSE : limite la taille des boutons */ gtk_box_pack_start (GTK_BOX (((GtkWidget **)param)[M_VB_CLASSE+offset]), ((GtkWidget ***)param)[M_HB_CLASSE+offset][((unsigned short **)param)[M_NB_CLASSE+offset][0]], TRUE,TRUE, 0); gtk_box_pack_start (GTK_BOX (((GtkWidget ***)param)[M_HB_CLASSE+offset][((unsigned short **)param)[M_NB_CLASSE+offset][0]]), ((GtkWidget ***)param)[M_PC_CLASSE+offset][((unsigned short **)param)[M_NB_CLASSE+offset][0]], TRUE,TRUE, 0); gtk_box_pack_start (GTK_BOX (((GtkWidget ***)param)[M_HB_CLASSE+offset][((unsigned short **)param)[M_NB_CLASSE+offset][0]]), ((GtkWidget ***)param)[M_NV_CLASSE+offset][((unsigned short **)param)[M_NB_CLASSE+offset][0]], TRUE,TRUE, 0);
Au final, ton programme, même s'il fonctionne, sera très dur à déboguer, même pour toi. Et il sera tout bonnement impossible à reprendre pour quelqu'un d'autre que toi, ce qui annule complètement tout avantage de la licence libre...
Utilisation de Glade avec Gtk+
Code::Blocks et Gtk+ sous Windows
Programmation orientée objet avec Gtk+ v3
- N'oubliez pas de consulter les FAQ Gtk et les cours et tutoriels Gtk
Autre exemple:
Tu galères à maintenir le nombre de caractères maximum par nom d'attribut, ainsi que le nombre de ces attributs...
Code : Sélectionner tout - Visualiser dans une fenêtre à part gchar nom[8][16]= "Force","Intelligence","Sagesse","Dextérité","Constitution","Charisme","Beauté","Humour"};
En utilisant un tableau de chaines de caractères plutôt qu'un tableau de tableaux de caractères, l'ajout ou la suppression d'éléments avant compilation devient beaucoup plus souple: plus besoin de toucher aux indices.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12 const gchar *attributes[] = { "Force", "Intelligence", "Sagesse", "Dextérité", "Constitution", "Charisme", "Beauté", "Humour", };
Pour connaitre le nombre d'éléments, tu peux utilise la macro G_N_ELEMENTS de la GLib qui va en réalité faire ceci:
C'est à dire le nombre d'éléments du tableau vaut la taille en octets du tableau divisée par la taille d'un élément du tableau.
Code : Sélectionner tout - Visualiser dans une fenêtre à part sizeof (attributes) / sizeof (*attributes)
Autre remarque: dans main.c tu définis:
Hé bien c'est là que tu devrais utiliser un structure au lieu d'un tableau.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 void * param[10]; /* pour le passage des paramètres */ unsigned short val[8]={1,2,3,4,5,6,7,8}; win = gtk_window_new (GTK_WINDOW_TOPLEVEL); /* déclaration d'une fenêtre complète */ param[0]=(void *)win; param[1]=(void *)val;
Quelque chose de cet acabit... Une fois le rôle de chaque structure de donnée identifié (je parle de structure de donnée au sens large, pas juste de structure C... Cela peut être une liste, un tableau, une struct, etc.) regrouper les fonctions qui les manipulent devient facile. Inspire toi de l'API GTK+, très bien ficelée à ce niveau là.
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 typedef struct { GtkWidget *main_window; /* ajoute les pointeurs vers tes autres widgets ici */ } Gui; typedef struct { Gui *gui; unsigned short val[8]={1,2,3,4,5,6,7,8}; /* même cela doit pouvoir être évité, mais je n'ai pas compris à quoi cela servait */ /* etc */ } Settings; [...] Gui *gui_new () { Gui *gui = g_new0 (Gui, 1); gui->main_window = gtk_window_new (GTK_WINDOW_TOPLEVEL); /* Crée tes widgets et ton interface graphique ici */ return Gui; } void gui_connect_signals (Gui *gui) { g_assert (gui != NULL); /* Connecte ici tes signaux */ } [...] Settings param; param.gui = gui_new (); gui_connect_signals (param.gui); /* etc. */
Ah, mais je n'ai pas dit cela moi
Tu peux tout à fait faire de l'objet en C. C'est ce que fait GTK+ ! Ce qu'il veut faire ne demande pas franchement d'héritage, mais plutôt de l'agrégation, qui se fait très bien en C en utilisant... des structures !
Utilisation de Glade avec Gtk+
Code::Blocks et Gtk+ sous Windows
Programmation orientée objet avec Gtk+ v3
- N'oubliez pas de consulter les FAQ Gtk et les cours et tutoriels Gtk
Je cherche à comprendre et à apprendre !
- Génial le coup du sizeof (attributes) / sizeof (*attributes). En réfléchissant, je peux éliminer des constantes ! La lisibilité reste la même si je rajoute :
nb : il n'y aurait pas une virgule de trop après "humour", dans ton exemple ?
Code : Sélectionner tout - Visualiser dans une fenêtre à part #define (NB_ATTRIBUTES sizeof (attributes) / sizeof (*attributes))
- Le coup de la structure, je suis toujours perplexe. Je comprends un intérêt : je regroupe d'un côté mes variables et de l'autre mes widgets. Mais, je ne vois pas en quoi ça va simplifier l'écriture ! Parce que là, je change une case de tableau par un ou deux niveau de structure. À la limite, ça peut simplifier la lecture peut-être, mais pas la raccourcir. Ceci dit, il faudrait que je modifie beaucoup de choses dans mon programme qui arrive presque à sa version finale !
Pour la connexion des signaux, ce n'est pas si facile que ça car je ne connaît pas à priori le nombre de case !- Attention au Settings param; : si ce n'est pas le main, une fois que la procédure a fini de s'exécuter, la variable param disparaît. Même si la fenêtre qu'elle a générée reste affichée. Donc, les variable contenues dans param parte dans les choux pour les appels de fonctions callback.
nb : et ma couleur des éléments d'une combo_box ?
Modérateur Mageia/Mandriva Linux
Amicalement VOOotre
Troumad Alias Bernard SIAUD à découvrir sur http://troumad.org
Mes tutoriels : xrandr, algorigramme et C, xml et gtk...
Utilisation de Glade avec Gtk+
Code::Blocks et Gtk+ sous Windows
Programmation orientée objet avec Gtk+ v3
- N'oubliez pas de consulter les FAQ Gtk et les cours et tutoriels Gtk
As-tu regardé du côté des GtkStyle?
Utilisation de Glade avec Gtk+
Code::Blocks et Gtk+ sous Windows
Programmation orientée objet avec Gtk+ v3
- N'oubliez pas de consulter les FAQ Gtk et les cours et tutoriels Gtk
LeN'est pas si génial :
Code : Sélectionner tout - Visualiser dans une fenêtre à part #define (NB_ATTRIBUTES sizeof (attributes) / sizeof (*attributes))
Code : Sélectionner tout - Visualiser dans une fenêtre à part /home/bs/Documents/add/gtk/perso/caract.c|1006|erreur: invalid application of sizeof to incomplete type struct struct_armes[] |
Modérateur Mageia/Mandriva Linux
Amicalement VOOotre
Troumad Alias Bernard SIAUD à découvrir sur http://troumad.org
Mes tutoriels : xrandr, algorigramme et C, xml et gtk...
Partager