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
| #include<gtk/gtk.h>
gboolean
g_callback_draw (GtkWidget *drawingarea, cairo_t *cr, gpointer data)
{
/* C'est dans cette fonction que l'on peut dessiner sur le widget de dessin.
* Nous allons partir du principe que nous disposons d'un tableau de données de 100x100.
* Pour l'exemple je crée ce tableau dans la fonction main(); et le transmets ici via le
* dernier pointeur transmis à cette fonction.
* Il me suffit de transtyper ce pointeur dans le bon type pour pouvoir travailler avec.
*/
guchar *matrice = (guchar*) data;
/* À partir de là je lance une boucle pour lire ce tableau et afficher dans le widget de
* dessin la couleur (niveau de gris) correspondante.
*
* Cairo fonctionne sur le principe de remplissage de surface délimitée. Pour ce faire on
* utilise des chemins. Afficher un seul point avec cette méhode est fastidieux et ne
* correspond pas forcément à la bonne méthode.
* Il serait "plus simple" de créer une image en mémoire et ensuite de l'afficher.
* J'ai décidé de te montrer comment dessiner avec Gtk plutôt que de te montrer comment
* créer une image. Si ca t'interresse je te ferai un exemple adhoc.
*/
gint x, y;
guchar color;
for (y=0; y<100; y++)
for (x=0; x<100; x++)
{
// Création d'un chemin pour dessiner un point. C'est un rectangle de côté = 1.
cairo_rectangle (cr, x, y, 1, 1);
// Lecture de la couleur dans le tableau aux coordonnées (x, y)
color = matrice [x + y*100];
/* On affecte cette couleur à chaque composante R, G, B.
* Ces composantes sont exprimées dans l'intervalle [0,1]. Il nous faut donc
* diviser par 255 (la valeur max que peut prendre color) pour obtenir son
* pendant dans l'intervalle [0, 1]
*/
cairo_set_source_rgb (cr, (gdouble)color/255, (gdouble)color/255, (gdouble)color/255);
// On demande pour finir à "peindre" ce point dans le widget de dessin.
cairo_fill(cr);
}
return FALSE;
}
int main (int argc,char **argv)
{
GtkWidget *window=NULL;
GtkWidget *scrolledwindow=NULL;
GtkWidget *drawingarea=NULL;
// Matrice à afficher
guchar matrice [10000];
// initialisation de la matrice aléatoire pour l'exemple
gint x;
for (x=0; x<10000; x++)
matrice[x] = g_random_double () * 255;
// initialisation des bibliothèques Gtk
gtk_init(&argc,&argv);
// Création d'une fenêtre principale
window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_default_size (GTK_WINDOW (window), 200, 200);
/* Pour une commodité d'affichage on insère dans la fenêtre principale un widget
* transparent qui va permettre de scroller l'image à l'intérieur (l'image pourra
* ainsi être plus grande que la fenêtre).
*/
scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
gtk_container_add (GTK_CONTAINER (window), scrolledwindow);
// Création d'un widget de dessin et insertion de celui-ci dans le widget de scrolling.
drawingarea = gtk_drawing_area_new ();
gtk_widget_set_size_request (drawingarea, 1000, 1000);
gtk_container_add (GTK_CONTAINER (scrolledwindow), drawingarea);
/* On affecte une fonction à exécuter lors de l'affichage du widget de dessin.
* Le dernier argument est la matrice que l'on transmet à la fonction pour traitement.
*/
g_signal_connect (G_OBJECT (drawingarea), "draw", (GCallback)g_callback_draw, matrice);
/* On affecte au signal "destroy" de la fenêtre principale la fonction qui permet
* de quitter la boucle principale d'affichage. Ainsi la fenêtre se ferme avant
* que le programme ne s'arrête.
*/
g_signal_connect (G_OBJECT (window), "destroy", (GCallback)gtk_main_quit, NULL);
/* On demande l'affichage de la fenêtre principale ainsi que de tous les widgets
* qui y sont insérés.
*/
gtk_widget_show_all(window);
// on lance la boucle principale Gtk.
gtk_main();
return 0;
} |