# Image Viewer (Vala)

Un peu plus qu'une simple application Gtk « Hello world ».
Projet de Documentation GNOME
gnome-doc-list@gnome.org
Johannes Schmid
jhs@gnome.org
Philip Chimento
philip.chimento@gmail.com
Tiffany Antopolski
tiffany.antopolski@gmail.com

# 1 Visionneur d'images

      Dans ce tutoriel, nous allons écrire une application qui charge et affiche un fichier image. Vous allez apprendre :

        comment paramétrer un projet de base en utilisant Anjuta IDE,
        comment écrire une application Gtk en Vala,
        quelques concepts de base sur la programmation GObject,

      Vous avez besoin de ce qui suit pour pouvoir suivre ce tutoriel :

        les connaissances de base du langage de programmation Vala.
        une copie installée de Anjuta.
        Vous pourriez trouver la référence API de gtk+-3.0 utile, bien qu'il ne soit pas nécessaire de suivre le tutoriel.

# 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 Créer un nouveau projet ou Fichier Nouveau Projet pour ouvrir l'assistant de création de projet.

Sélectionnez Gtk+ (Simple) dans l'onglet Vala, cliquez sur Continuer et saisissez vos informations sur les pages suivantes. Utilisez image-viewer comme nom de projet et de répertoire.

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 Accordeur de guitare si vous souhaitez savoir comment utiliser le constructeur d'interface GtkBuilder.

Cliquez sur Continuer et le projet est créé. Ouvrez src/image_viewer.vala depuis l'onglet Projet ou l'onglet Fichiers. Vous verrez apparaître ce code :

using GLib; using Gtk;

public class Main : Object {

public Main () { Window window = new Window(); window.set_title ("Hello World"); window.show_all(); window.destroy.connect(on_destroy); }

public void on_destroy (Widget window) { Gtk.main_quit(); }

static int main (string[] args) { Gtk.init (ref args); var app = new Main ();

Gtk.main ();

return 0; } }

# Première construction du programme

Ce programme charge une fenêtre (vide) à partir du fichier de description de l'interface et l'affiche. Vous trouverez plus de détails ci-dessous ; passez cette liste si vous comprenez les bases :

Les deux lignes `using` du début importent des espaces de noms que nous n'aurons plus à nommer explicitement.

Le constructeur de la classe principale `Main` crée une nouvelle fenêtre (vide) et connecte un signal pour quitter l'application quand cette 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 `statique main` est exécutée par défaut quand vous lancez une application Vala. Elle appelle d'autres fonctions qui créent la classe `Main`, configurent puis exécutent 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).

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

Pour configurer le répertoire de compilation, modifiez la Configuration à Par défaut et cliquez sur Exécuter. Il ne faut le faire qu'une seule fois, à la première compilation.

# Création de l'interface utilisateur

Nous allons maintenant donner vie à la fenêtre vide. GTK organise l'interface utilisateur avec des `Gtk.Container` 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 `Gtk.Box` :

Ajoutez les lignes suivantes au dessus de la classe `Main` :

private Window window; private Image image;

Remplacez maintenant le constructeur actuel par celui ci-dessous :

public Main () {

window = new Window (); window.set_title ("Image Viewer in Vala");

// Set up the UI var box = new Box (Orientation.VERTICAL, 5); var button = new Button.with_label ("Open image"); image = new Image ();

box.pack_start (image, true, true, 0); box.pack_start (button, false, false, 0); window.add (box);

// Show open dialog when opening a file button.clicked.connect (on_open_image);

window.show_all (); window.destroy.connect (main_quit); }

Les deux premières lignes sont les parties de l'interface graphique auxquelles nous aurons besoin d'accéder depuis plus d'une méthode. Nous les déclarons avant afin qu'elles soient accessibles depuis la classe plutôt que seulement dans la méthode où elles sont crées.

Les premières lignes du constructeur créent la fenêtre vide. Les lignes suivantes créent les éléments graphiques dont nous avons besoin : un bouton pour ouvrir une image, l'élément graphique image lui-même et la boîte que nous utilisons comme conteneur.

Les appels à `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.

Nous devons définir ce qui se produit lorsque l'utilisateur clique sur le bouton. GTK utilise le concept de signaux.

Lorsque le bouton est cliqué, il émet le signal `clicked` que nous pouvons connecter à des actions (définies dans une fonction de rappel).

On le fait en utilisant la méthode `connect` du signal `clicked` du bouton qui dans ce cas indique à GTK d'appeler la fonction de rappel (pas encore définie) `on_image_open` lorsque le bouton est cliqué. Nous définirons la fonction de rappel dans la prochaine section.

Dans la fonction de rappel, nous avons besoin d'accéder aux éléments graphiques `window` (fenêtre) et `image`, c'est pourquoi nous les définissons comme membres privés (private) au début de notre classe.

Le dernier appel `connect` permet d'être sûr que l'application quitte lorsque la fenêtre est fermée. Le code généré par Anjuta appelle une fonction de rappel `on_destroy` qui appelle `Gtk.main_quit` bien qu'il soit plus facile de connecter directement notre signal à `main_quit`. Vous pouvez supprimer la méthode `on_destroy`.

# Affichage de l'image

Nous allons maintenant définir le gestionnaire de signal pour le signal `clicked` du bouton ci-dessus. Ajoutez ce code après le constructeur :

public void on_open_image (Button self) { var filter = new FileFilter (); var dialog = new FileChooserDialog ("Open image", window, FileChooserAction.OPEN, Stock.OK, ResponseType.ACCEPT, Stock.CANCEL, ResponseType.CANCEL); filter.add_pixbuf_formats (); dialog.add_filter (filter);

switch (dialog.run ()) { case ResponseType.ACCEPT: var filename = dialog.get_filename (); image.set_from_file (filename); break; default: break; } dialog.destroy (); }

C'est un peu compliqué, donc décortiquons cette partie étape par étape :

Un gestionnaire de signal est un type de fonction de rappel qui est appelé lorsqu'un signal est émis. Ici les termes sont utilisés indifféremment.

Le premier argument de la fonction de rappel est toujours l'élément graphique qui a envoyé le signal. Parfois d'autres arguments apparaissent derrière reliés au signal, mais clicked n'en a aucun.

Dans ce cas, le `bouton` envoie le signal `clicked` qui est connecté à la fonction de rappel `on_open_image` :

button.clicked.connect (on_open_image);

Le méthode `on_open_image` prend comme paramètre le bouton qui a émis le signal :

public void on_open_image (Button self)

La prochaine ligne intéressante est celle où est créée la boîte de dialogue pour choisir le fichier. Le constructeur de `FileChooserDialog` prend comme argument le titre, la fenêtre parente de la boîte de dialogue et plusieurs options telles que l'étiquette des boutons et les actions 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 sont 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 qui est un élément graphique qui affiche une image. Un objet filtre est d'abord créé ; ensuite nous ajoutons tous les types de fichiers pris en charge par `Gdk.Pixbuf` (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.

`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, `dialog.run` retourne la valeur ResponseType `ResponseType.ACCEPT` (il retourne la valeur `ResponseType.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 récupère le nom de fichier de l'image sélectionnée par l'utilisateur et indique à l'élément graphique `GtkImage` de charger et d'afficher l'image choisie.

La dernière ligne de cette méthode détruit la boîte de dialogue Open car nous n'en avons 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 Construire Construire le projet pour tout reconstruire et faites Exécuter Exécuter pour lancer l'application.

Si ce n'est pas encore fait, sélectionnez l'application 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 :

Paramètre en sorte que lorsque la fenêtre s'ouvre, elle fasse une taille de départ spécifiée, par exemple 200 X 200 pixels.

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.

Vous pouvez utiliser GIO pour gérer des transferts de fichiers en ligne et des choses du même type et GNOME Scan pour gérer les documents scannés.