Je reviens une dernière fois à la charge avec un code modifié. Le but est ici de supprimer complètement l'utilisation de la structure SJeu sans aucune déclaration en globale, il va de soit .

Pour obtenir ce résultat il faut pousser un peu dans la connaissance de GTK+ mais il est tout à fait compréhensible. J'ai décidé de l'éditer pour montrer qu'il est possible d'extraire un nombre important d'informations à partir des widgets de GTK+.

Pour arriver au résultat il faut y aller par étape. Reprenons la structure SJeu en l'état :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
typedef struct
{
    int        i;
    int        j;
    int        n;
    GtkWidget *pTable;
    GtkWidget *pButton;
}SJeu;
Lors de l'ajout de chaque bouton, on crée un nouvel élément de SJeu. pTable est un pointeur qui ne change pas dans le temps. Donc on se retrouve à copier ce pointeur n*n fois. Une perte d'espace inutile. Comment faire pour le supprimer de la structure?
Gtk+ met à notre disposition la fonction gtk_widget_get_ancestor();. Grâce à elle on peut récupérer le widget parent dun widget donné. Son conteneur en somme. Comme nous avons dans le CALLBACK le pointeur pButton, nous pouvons alors obtenir facilement son conteneur. C'est à dire pTable.

Le pointeur pButton est totalement inutile puisque automatiquement récupéré dans le CALLBACK.

Première difficulté. Comment récupérer n?
C'est ici qu'il faut un peu triturer GTK+. Il est possible de récupérer les widgets fils d'un containeur GtkTable sous forme de GList. Le premier élément de la liste correspond au widget en bas à droite. Le deuxième élément au widget en bas à la deuxième position en partant de la droite. Et ainsi de suite.
L'idée est donc de récupérer cette liste grâce à la fonction gtk_container_get_children();. Une fois récupérée on peut obtenir pour chaque widget de la liste sa position en pixel. On peut alors comparer ces positions pour en extraire la longueur d'une ligne. je ne détaille pas plus ici, le code est plus explicite qu'un long discours.

Une fois n récupéré on utilise la même technique pour extraire i et j.

Remarque:
L'algorithme présenté ici ne fonctionne que pour une table carrée.

Voici donc le code nettoyé:
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
#include <stdlib.h>
#include <gtk/gtk.h>
 
void afficher_image(GtkWidget* pTable, gpointer user_data);
 
 
int main(int argc, char **argv)
{
	GtkWidget *pWindow;
	GtkWidget *pTable;      // Table bouton
	int i=0, j=0, n=20;
	GtkWidget *pImage[n*n];
	GtkWidget *pButton=NULL;
 
	gtk_init(&argc, &argv);
 
	/* Creation de la fenetre */
	pWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL);
	gtk_window_set_title(GTK_WINDOW(pWindow), "Demineur");
	gtk_window_set_default_size(GTK_WINDOW(pWindow), n*10, n*10);
	g_signal_connect(G_OBJECT(pWindow), "destroy", G_CALLBACK(gtk_main_quit), NULL);
 
	/* Creation et insertion de la table n lignes n colonnes */
	pTable=gtk_table_new(n,n,TRUE);
	gtk_container_add(GTK_CONTAINER(pWindow), GTK_WIDGET(pTable));
 
	for (i = 0; i < n; i++)
	{
		for (j = 0; j < n; j++)
		{
			/* n*i donne 0 au premier passage, n au deuxième, 2*n au troisième, etc.
			* 0+j = 0 au premier passage, 1 au deuxième, etc. */
			pButton=gtk_button_new();
 
			gtk_table_attach_defaults (GTK_TABLE(pTable), pButton, j, j+1, i, i+1);
			pImage[n*i+j] =gtk_image_new_from_file(".\\Images\\case.jpg");
			gtk_container_add(GTK_CONTAINER(pButton), pImage[n*i+j]);
 
			g_signal_connect(G_OBJECT(pButton), "clicked", G_CALLBACK(afficher_image), NULL);
		}
	}
 
	gtk_widget_show_all(pWindow);
	gtk_main();
 
	return EXIT_SUCCESS;
}
 
void afficher_image(GtkWidget* pButton, gpointer user_data)
{
	GtkWidget* pImage[200];
	GtkWidget *pTable=gtk_widget_get_ancestor(pButton, GTK_TYPE_TABLE);
	GList *ButtonList=gtk_container_get_children(GTK_CONTAINER(pTable));
	GList *list=NULL;
	int compteur=0;
	int n=0;
	int i=0, j=0;
	int repere=0;
	GtkAllocation Allocation;
	GtkWidget *Widget=NULL;
 
	// Récupération de n.
	Widget=(GtkWidget*)ButtonList->data;
	list=g_list_first(ButtonList);
	gtk_widget_get_allocation(Widget, &Allocation);
	repere=Allocation.y;
	while (list)
	{
		gtk_widget_get_allocation((GtkWidget*)list->data, &Allocation);
		if (Allocation.y!=repere) break;
		n++;
		list=g_list_next(list);
	}
 
	//Récupération de i et j
	list=g_list_first(ButtonList);
	for (j=n-1; j>=0; j--)
	{
		for (i=n-1; i>=0; i--)
		{
			if (pButton==(GtkWidget*)list->data)
			{
				goto fin;
			}
			list=g_list_next(list);
		}
	}
 
	fin:
g_print("%d,%d,%d\n", i, j, n);
 
	// Libération mémoire de la liste devenue inutile.
	g_list_free(ButtonList);
 
        compteur=i+(j*n);
	pImage[compteur] = gtk_image_new_from_stock(GTK_STOCK_ABOUT, GTK_ICON_SIZE_MENU);
	gtk_button_set_image(GTK_BUTTON(pButton), pImage[compteur]);
}
Remarque finale:
J'utilise ici l'instruction goto dont je ne suis vraiment pas amoureux. Mais bon ca rend plus lisible le code. Il serait possible de passer outre en utilisant une instrutionwhile() en lieu et place des deux boucles for, mais bon, je fatigue là...