Image viewer (C) Un peu plus qu'une simple application Gtk « Hello world ». Projet de Documentation GNOME gnome-doc-list@gnome.org Johannes Schmid jhs@gnome.org Marta Maria Casetti mmcasetti@gmail.com 2013 Luc Rebert, traduc@rebert.name 2011 Alain Lojewski, allomervan@gmail.com 2011-2012 Luc Pionchon pionchon.luc@gmail.com 2011 Bruno Brouard annoa.b@gmail.com 2011-12 Luis Menina liberforce@freeside.fr 2014 Image viewer

Dans ce tutoriel, vous allez apprendre :

quelques concepts de base de la programmation en C/GObject,

comment écrire une application GTK en C.

Création d'un projet dans Anjuta

Avant de commencer à programmer, vous devez ouvrir un nouveau projet dans Anjuta. Ceci crée tous les fichiers qui vous sont nécessaires pour construire et exécuter votre programme plus tard. C'est aussi utile pour tout regrouper en un seul endroit.

Lancez Anjuta et cliquez sur FichierNouveauProjet pour ouvrir l'assistant de création de projet.

Choose GTK+ (Simple) from the C tab, click Continue, and fill out your details on the next few pages. Use image-viewer as project name and directory.

Assurez-vous d'avoir désactivé Utiliser GtkBuilder pour l'interface utilisateur car nous allons créer l'interface utilisateur manuellement dans cet exemple. Consultez le tutoriel Guitar-Tuner pour un exemple d'utilisation du constructeur d'interfaces.

Cliquez sur Appliquer et votre projet est créé. Ouvrez src/main.c depuis l'onglet Projet ou l'onglet Fichiers. Vous devez voir apparaître du code commençant par les lignes :

#include ]]>
Première construction du programme

« C » est un langage plutôt verbeux, donc ne soyez pas surpris par la quantité de code que contient le fichier. La plupart du code est générique. Il charge une fenêtre (vide) et l'affiche. Vous trouverez plus de détails ci-dessous ; passez cette liste si vous comprenez les bases :

Les trois lignes #include du haut incorporent les bibliothèques config (définitions utiles pour la construction autoconf), gtk (interface utilisateur) et gi18n (pour internationalisation). Les fonctions de ces bibliothèques seront utilisées dans le reste du programme.

La fonction create_window crée une nouvelle fenêtre (vide) et connecte un signal pour quitter l'application quand la fenêtre est fermée.

Connecter des signaux, c'est décider de ce qui doit se passer quand on appuie sur un bouton ou quand quelque chose d'autre se produit. Ici, la fonction destroy est appelée (et quitte l'application) quand la fenêtre est fermée.

La fonction main est exécutée par défaut quand vous lancez une application C. Elle appelle d'autres fonctions qui configurent puis lancent l'application. La fonction gtk_main démarre la boucle principale de GTK, qui lance l'interface utilisateur et commence à écouter les événements (comme des clics de souris ou des appuis sur des touches).

La définition conditionnelle ENABLE_NLS configure gettext qui est un environnement pour la traduction des applications. Ces fonctions définissent la façon dont les objets de traduction doivent prendre en charge votre application quand vous l'exécutez.

Le programme est prêt à être utilisé, donc vous pouvez le compiler en cliquant sur ConstruireConstruire le projet ou en appuyant sur MajF7.

Cliquez sur Exécuter dans la fenêtre suivante pour configurer une construction avec débogage. Vous ne devez le faire qu'une seule fois, lors de la première exécution.

Création de l'interface utilisateur

Nous allons maintenant donner vie à la fenêtre vide. GTK organise l'interface utilisateur avec des GtkContainer qui peuvent contenir d'autres éléments graphiques et même d'autres conteneurs. Ici, nous allons utiliser le plus simple conteneur disponible, une boîte GtkBox :

Les premières lignes créent les éléments graphiques que nous voulons utiliser : un bouton pour pouvoir ouvrir une image, l'élément graphique image lui-même et la boîte qui nous sert de conteneur. Nous utilisons des macros comme GTK_BOX pour contrôler et convertir de manière dynamique les types d'objet ce qui est nécessaire car le C n'est pas prévu nativement pour prendre en charge la programmation orientée objets.

Les appels à gtk_box_pack_start ajoutent les deux éléments graphiques à la boîte et définissent leur comportement. L'image va s'étendre pour occuper tout l'espace disponible alors que le bouton va prendre juste la taille nécessaire. Notez que nous ne définissons pas explicitement les dimensions des éléments graphiques. Avec GTK, ce n'est habituellement pas nécessaire car cela facilite grandement l'obtention d'une bonne disposition pour différentes tailles de fenêtre. La boîte est ensuite ajoutée dans la fenêtre.

Il nous faut définir ce qui se passe quand l'utilisateur clique sur le bouton. GTK utilise le concept de signaux. Quand le bouton est cliqué, il envoie le signal clicked qu'il est possible de relier à une action. Cela a été réalisé avec la méthode g_signal_connect qui commande à GTK d'appeler la fonction on_open_image quand le bouton est cliqué et de transmettre l'image à cette fonction comme argument additionnel. Nous définirons la fonction de rappel à la section suivante.

Le dernier signal g_signal_connect() assure que l'application quitte quand la fenêtre est fermée.

Pour finir, assurez-vous de remplacer l'appel gtk_widget_show de la fonction principale main() par gtk_widget_show_all() pour afficher la fenêtre et tous les éléments graphiques qu'elle contient.

Affichage de l'image

Nous allons maintenant définir le gestionnaire de signal pour le signal clicked du bouton ci-dessus. Ajoutez ce code avant la méthode create_window().

C'est un peu plus compliqué que tout ce que nous avons essayé jusqu'à présent, donc décortiquons cette partie étape par étape :

Le premier argument du signal est toujours l'élément graphique qui envoie le signal. Il y a parfois d'autres arguments attachés au signal, mais clicked n'en a aucun. Ensuite vient l'argument user_data qui est un pointeur vers les données transmises en connectant le signal. Ici, c'est notre objet GtkImage.

La prochaine ligne intéressante est celle où est créée la boîte de dialogue pour choisir le fichier avec gtk_file_chooser_dialog_new. La fonction prend comme argument le titre et la fenêtre parente de la boîte de dialogue et plusieurs options telles que le numéro des boutons et leurs valeurs correspondantes.

Notez que nous utilisons les noms de bouton de la collection (stock) Gtk au lieu de saisir manuellement « Cancel » ou « Open ». L'avantage d'utiliser les noms de la collection est que les étiquettes des boutons seront déjà traduites dans la langue de l'utilisateur.

Les deux lignes suivantes limitent la boîte de dialogue Open à l'affichage des seuls fichiers pouvant être ouverts par GtkImage. Un objet filtre est d'abord créé ; ensuite nous ajoutons tous les types de fichier pris en charge par GdkPixbuf (ce qui inclut la plupart des formats d'image comme PNG ou JPEG) au filtre. Enfin, nous appliquons ce filtre à la boîte de dialogue Open.

gtk_dialog_run affiche la boîte de dialogue Open. La boîte de dialogue attend que l'utilisateur choisisse une image ; quand c'est fait, gtk_dialog_run retourne la valeur GTK_RESPONSE_ACCEPT (il retourne la valeur GTK_RESPONSE_CANCEL si l'utilisateur clique sur Cancel). L'instruction switch teste cette réponse.

Supposons que l'utilisateur a cliqué sur le bouton Ouvrir, la ligne suivante attribue le nom du fichier image choisi par l'utilisateur aux propriétés file du GtkImage. Ensuite, GtkImage charge et affiche l'image choisie.

Dans la dernière ligne de cette méthode, nous détruisons la boîte de dialogue Open car on n'en a plus besoin. La destruction masque automatiquement la boîte de dialogue.

Construction et lancement de l'application

À ce stade, tout le programme est fonctionnel. Cliquez sur ConstruireConstruire le projet pour tout reconstruire et faites ExécuterExécuter pour lancer l'application.

Si ce n'est pas encore fait, sélectionnez l'application Debug/src/image-viewer dans la boîte de dialogue qui s'affiche et cliquez sur Exécuter. Amusez-vous bien !

Implémentation de référence

Si vous rencontrez des difficultés avec ce tutoriel, comparez votre programme à ce programme de référence.

Les étapes suivantes

Voici quelques idées sur la manière d'étendre ce simple exemple :

Faire que l'utilisateur puisse sélectionner un dossier plutôt qu'un fichier et fournir les contrôles pour naviguer parmi toutes les images d'un dossier.

Appliquer au hasard des filtres et des effets à l'image quand elle est chargée et permettre à l'utilisateur d'enregistrer l'image modifiée.

GEGL fournit de puissantes possibilités de manipulation d'image.

Permettre à l'utilisateur de charger des images depuis des sites de partage, des scanners ou d'autres sources plus sophistiquées.

You can use GIO to handle network file transfers and the like, and GNOME Scan to handle scanning.