Lors d'un précédent fil de discussion, nous avions échangé sur le typage des pointeurs sur les différents widgets (faut-il tous les déclarer GtkWidget* ou par leur type réel ?), sachnat que généralement, la fonction gtk_xxx_new () renvoie un GtkWidget*, mais ce n'est pas systématique (voir par exemple gtk_adjustment_new () qui renvoie un GtkAdjustment*).

De plus, ça m'agace un peu de passer mon temps à caster les pointeurs.

Je vous propose la programmation suivante d'un petit exemple du livre d'Andrew Krause transposé en GTK+ 3.

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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
#include <stdlib.h> /* Définition de EXIT_SUCCESS */
#include <gtk/gtk.h>
 
/* Définition des unions regroupant les différents types de widgets */
/* A définir pour tous les objets de la bibliothèque et à mettre dans un fichier ".h" */
 
typedef union
 
	{
 
		GObject			*object;
		GInitiallyUnowned	*initiallyunowned;
		GtkWidget		*widget;
		GtkContainer		*container;
		GtkBin			*bin;
		GtkWindow		*window;
 
	} GTKWINDOW;
 
typedef union
 
	{
 
		GObject			*object;
		GInitiallyUnowned	*initiallyunowned;
		GtkWidget		*widget;
		GtkContainer		*container;
		GtkGrid			*grid;
 
	} GTKGRID;
 
typedef union
 
	{
 
		GObject			*object;
		GInitiallyUnowned	*initiallyunowned;
		GtkAdjustment		*adjustment;
 
	} GTKADJUSTMENT;
 
typedef union
 
	{
 
		GObject			*object;
		GInitiallyUnowned	*initiallyunowned;
		GtkWidget		*widget;
		GtkEntry		*entry;
		GtkSpinButton		*spinbutton;
 
	} GTKSPINBUTTON;
 
typedef union
 
	{
 
		GObject			*object;
		GInitiallyUnowned	*initiallyunowned;
		GtkWidget		*widget;
		GtkRange		*range;
		GtkScale		*scale;
 
	} GTKSCALE;
 
typedef union
 
	{
 
		GObject			*object;
		GInitiallyUnowned	*initiallyunowned;
		GtkWidget		*widget;
		GtkContainer		*container;
		GtkBin			*bin;
		GtkButton		*button;
		GtkToggleButton		*togglebutton;
		GtkCheckButton		*checkbutton;
 
	} GTKCHECKBUTTON;
 
/* structure regroupant les trois widgets (permet de passer un pointeur global à la fonction value_changed) */
 
typedef struct
 
{
 
	GTKSPINBUTTON	spin;
	GTKSCALE	scale;
	GTKCHECKBUTTON	check;
 
} Widgets;
 
/* Prototype de la fonction de callback */
 
static void cb_value_changed (GtkWidget *, Widgets *);
 
int main (int argc, char *argv[])
 
{
 
/* Déclaration des variables */
 
	GTKWINDOW window;
	GTKGRID grid;
	GTKADJUSTMENT adj1, adj2;
 
	Widgets *w = (Widgets *) g_malloc (sizeof (Widgets));
 
/* Initialisation de GTK+ */
 
	gtk_init (&argc, &argv);
 
/* Création des widgets */
 
	window.widget = gtk_window_new (GTK_WINDOW_TOPLEVEL);
	grid.widget = gtk_grid_new ();
	adj1.adjustment = gtk_adjustment_new (0.5, 0.0, 1.02, 0.01, 0.02, 0.02);
	adj2.adjustment = gtk_adjustment_new (0.5, 0.0, 1.02, 0.01, 0.02, 0.02);
 
	w->spin.widget = gtk_spin_button_new (adj1.adjustment, 0.01, 2);
	w->scale.widget = gtk_scale_new (GTK_ORIENTATION_HORIZONTAL, adj2.adjustment);
	w->check.widget = gtk_check_button_new_with_label ("Synchronize Spin and Scale");
 
/* Paramétrage des widgets */
 
	gtk_window_set_title (window.window, "Exercise 4-2");
	gtk_container_set_border_width (window.container, 10);
 
	gtk_grid_set_row_spacing (grid.grid, 5);
	gtk_grid_set_column_homogeneous (grid.grid, FALSE);
	gtk_grid_set_row_homogeneous (grid.grid, FALSE);
 
	gtk_toggle_button_set_active (w->check.togglebutton, TRUE);
	gtk_scale_set_digits (w->scale.scale, 2);
 
/* Attachement des widgets les uns aux autres */
 
	gtk_grid_attach (grid.grid, w->spin.widget, 0 , 0, 1, 1);
	gtk_grid_attach_next_to (grid.grid, w->scale.widget, w->spin.widget, GTK_POS_BOTTOM, 1, 1);
	gtk_grid_attach_next_to (grid.grid, w->check.widget, w->scale.widget, GTK_POS_BOTTOM, 1, 1);
 
	gtk_container_add (window.container, grid.widget);
 
/* Attachement des signaux aux widgets */
 
	g_signal_connect (window.object, "destroy", G_CALLBACK (gtk_main_quit), NULL);
 
	g_signal_connect (w->spin.object, "value_changed", G_CALLBACK (cb_value_changed), (gpointer) w);
	g_signal_connect (w->scale.object, "value_changed", G_CALLBACK (cb_value_changed), (gpointer) w);
 
/* Affichage des widgets */
 
	gtk_widget_show_all (window.widget);
 
/* Et c'est parti */
 
	gtk_main ();
 
/* Libération de la mémoire */
 
	g_free (w);
 
	return EXIT_SUCCESS;
}
 
static void cb_value_changed (GtkWidget *widget, Widgets *w)
 
{
 
/* Déclaration des variables */
 
	gdouble val1, val2;
 
/* Récupère les valeurs des deux widgets */
 
	val1 = gtk_spin_button_get_value (w->spin.spinbutton);
	val2 = gtk_range_get_value (w->scale.range);
 
/* Si la synchronisation est activée */
 
	if (gtk_toggle_button_get_active (w->check.togglebutton) && val1 != val2)
 
	{
 
/* Ajuste la valeur du widget "passif" par rapport à celle du widget qui a activé le signal */
 
		if (GTK_IS_SPIN_BUTTON (widget)) gtk_range_set_value (w->scale.range, val1);
		else gtk_spin_button_set_value (w->spin.spinbutton, val2);
 
	}
 
}
Codé comme ça, le pointeur porte en lui-même son type. Plus besoin de caster.

Merci de me donner votre avis sur cette manière de faire.

Jean-Marie