Programmation avec GTK# en .NET

Lainé Vincent

Ce tutoriel a pour but de faire découvrir au lecteur la programmation graphique sous .NET avec GTK#.
Les exemples ont tous été compilés avec Mono sous Linux.

N'hésitez pas à commenter cet article ! Commentez

- Titre : Programmation avec GTK# en .NET

- Auteur : Lainé Vincent

- Parution : 26 septembre 2005

- Mise à jour : 3 mars 2020

- Licence : Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright ® 2013 Lainé Vincent. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Sommaire

- I. Introduction à GTK (+ et # )

- I-A. Qu'est-ce que GTK+ ?

- I-B. Qu'est-ce que GTK#

- II. Installation de GTK#

- II-A. Prérequis

- II-B. Installation à partir d'un paquet binaire

- II-C. Installation à partir des sources

- II-D. Euh, ça ne configure/compile/install pas

- II-D-1. Ça ne configure pas…

- II-D-2. Ça ne compile pas

- II-D-3. Ça n'installe pas

- III. Le projet 'LogView'

- III-A. Création de la fenêtre principale

- III-B. Ajouter un bouton

- III-C. Le placement par conteneur

- III-D. Le système de menu de GTK#

- IV. Gestion des évènements

- V. Le reste du code

- V-A. Les boîtes de dialogue

- VI. (petite) grille de correspondance des composants entre GTK# et System.Windows.Forms

- VII. La compilation

- VIII. Ressources

- IX. Remerciements

I - Introduction à GTK (+ et # )

I-A - Qu'est-ce que GTK+ ?

GTK signifie Gimp ToolKit est a été développé à l'origine pour le développement du logiciel de dessin « The GIMP ». Peu à peu c'est devenu un framework de développement écrit en C qui fournit un certain nombre de composants de base destinés à la création d'interfaces graphiques.
Actuellement GTK+ est le framework de composants de base pour l'environnement de bureau GNOME sous Linux. À titre d'information, l'autre environnement de bureau majeur sous Linux est KDE qui s'appuie lui sur la bibliothèque Qt écrite en C++. Un projet pour porter Qt sous Mono est en cours, mais rien de stable n'est encore sorti.

I-B - Qu'est-ce que GTK#

GTK# est le projet visant à créer une surcouche à GTK+ afin de pouvoir utiliser les composants GTK+ avec Mono et .NET.
Celui-ci est disponible en version 1.0 (stable) ou 2.0 (en cours de développement) pour Mono et .NET.
Actuellement GTK# 1.0 utilise les composants de GTK+ 2.4 alors que GTK# 2.0 utilise ceux de GTK+ 2.6.

II - Installation de GTK#

II-A - Prérequis

Afin de pouvoir installer GTK# vous devez avoir GTK+ installé sur votre machine.
Attention afin de pouvoir compiler GTK# vous devez avoir les fichiers de développement de GTK+. Si vous l'avez installé à partir des sources ou si votre système de package ne différencie pas la bibliothèque et ses fichiers de développement, vous n'aurez pas de problème.
Ensuite vous devez avoir évidemment Mono installé (voir mon article sur Mono).

II-B - Installation à partir d'un paquet binaire

Des adresses de paquets précompilés sont disponibles en fin d'article.

Si vous avez installé la version bundle de Mono vous disposez déjà de GTK# (version 1.0).
Sinon vous pouvez aussi regarder sur les miroirs de votre distribution s'il n'existe pas de paquet précompilé.

II-C - Installation à partir des sources

Après avoir récupéré les sources, vous faites :

$> tar xvfz ./gtk-sharp-1.9.2.tar.gz
$> cd ./gtk-sharp-1.9.2
$> ./configure
$> make
$> su
#> make install
#> exit

Attention sur certaines distributions comme la Mandriva (ancienne Mandrake), il faut installer les paquetages de développement (Gtk-Devel sur Mandriva) afin de pouvoir installer GTK# à partir des sources.

II-D - Euh, ça ne configure/compile/install pas

II-D-1 - Ça ne configure pas…

Vérifiez les points suivants :

Symptômes :

Remèdes:

Impossible de trouver Mono

Vous avez installé Mono à partir des sources vérifiez que les fichiers de configuration (.pc) sont copiés au bon endroit sur votre distribution. (Par défaut /usr/local/lib/pkgconfig/)

Impossible de trouver GTK+

Même chose, mais pour le fichier gtk.pc

II-D-2 - Ça ne compile pas

Vérifiez que vous utilisez une version récente de gcc, car GTK# compile du code C.

II-D-3 - Ça n'installe pas

Vérifiez que vous êtes bien en root pour lancer la commande 'make install'.

III - Le projet 'LogView'

Afin d'illustrer les grands principes de la programmation avec GTK#, nous allons écrire un petit programme qui va se contenter de charger un fichier (de log par exemple) dans une zone de texte.

III-A - Création de la fenêtre principale

Les commentaires dans le code vous permettront de comprendre le but des différentes commandes :

using System;
using Gtk;

namespace Gtk_Sharp
{

public class MainForm : Gtk.Window //On définit une nouvelle fenêtre par héritage
{

public MainForm() : base("LogView") //On définit le titre de la fenêtre
{
this.InitializeComponment();
}

private void InitializeComponment()
{

//MainForm
this.Name = "MainForm";
this.DefaultWidth = 600;
this.DefaultHeight = 480;
this.DeleteEvent += new Gtk.DeleteEventHandler(this.WindowsDelete);
this.ShowAll();
}

private void WindowsDelete(object sender, Gtk.DeleteEventArgs e)
{
//On détruit la fenêtre principale
this.Destroy();
//On quitte le loopback principal
Application.Quit();
//On n'accepte plus les messages
e.RetVal = true;
}

public static void Main(string[] args)
{
Console.WriteLine("Lancement de LogView");

//Initialisation de GTKSharp
Application.Init();
new MainForm();
//Lancement du 'loopback' principal
Application.Run();

Console.WriteLine("Arret de LogView");
}

}
}

III-B - Ajouter un bouton

Modifications pour ajouter un composant

//On ajoute un bouton pour quitter le programme
private Gtk.Button quit;

//quit
this.quit = new Gtk.Button("Quitter");

//MainForm
this.Add(this.quit);

après compilation du programme, voilà ce que vous obtenez :

Vous constatez que le bouton ainsi ajouté occupe toute la place dans la fenêtre.
En effet GTK# (et GTK+) fonctionne, pour le placement des composants, par conteneurs.

III-C - Le placement par conteneur

Qu'est-ce que le placement par conteneur ?
Les conteneurs offrent une méthode de placement des composants très puissante, car ils s'occupent du placement par rapport aux autres conteneurs et surtout de redimensionner les composants en cas de besoin par exemple un redimensionnement de la fenêtre.
Les conteneurs sont de deux catégories principales :
- les HBox qui fournissent un placement de composants à l'horizontale ;
- les VBox qui fournissent un placement de composants à la verticale.

Le placement par conteneur requiert un peu d'habitude avant d'arriver à faire ce que l'on veut, mais quand on le maîtrise (au bout de deux, trois fenêtres faites) c'est un moyen de placement très efficace.
Voyons maintenant comment nous allons nous organiser pour faire le placement des composants dans notre projet :

Ce petit schéma montre le découpage de la fenêtre principale afin de voir comment placer les conteneurs et les composants.Notez qu'un conteneur peut contenir d'autres conteneurs.
Je vous recommande de procéder ainsi pour créer vos interfaces afin de ne pas vous perdre dans les conteneurs.
Voici le code notre application :

using System;
using Gtk;

namespace Gtk_Sharp
{

public class MainForm : Gtk.Window //On définit une nouvelle fenêtre par héritage
{

//On ajoute un bouton pour quitter le programme
private Gtk.Button quit;
// Bouton pour sauvegarde le fichier de log ailleurs
private Gtk.Button saveAs;
// Bouton pour vider l'espace de texte
private Gtk.Button clear;

// Menu principal
private Gtk.MenuBar menuBar;
private Gtk.MenuItem m_file;
//Menu Principal
private Gtk.Menu file_menu;
private Gtk.MenuItem m_fichier;
private Gtk.MenuItem m_exit;

// Zone de visualisation du texte
private Gtk.TextView textView;
//HBox principale pour le placement des conteneurs
private Gtk.HBox hBoxButton;
//VBox pour le placement des boutons en bas de la fenêtre
private Gtk.VBox vBoxPrinci;

public MainForm() : base("LogView") //On définit le titre de la fenêtre
{
this.InitializeComponment();
}

private void InitializeComponment()
{
//quit
this.quit = new Gtk.Button("Quitter");

//saveAs
this.saveAs = new Gtk.Button("Enregistrer sous");

//clear
this.clear = new Gtk.Button("Vider");

//textView
this.textView = new Gtk.TextView();

//m_fichier
this.m_fichier = new Gtk.MenuItem("Fichier");

//m_exit
this.m_exit = new Gtk.MenuItem("Quitter");

//file_menu
this.file_menu = new Gtk.Menu();
this.file_menu.Append(this.m_fichier);
this.file_menu.Append(this.m_exit);

//file_menu
this.m_file = new Gtk.MenuItem("Fichier");
this.m_file.Submenu = this.file_menu;

//menuBar
this.menuBar = new Gtk.MenuBar();
this.menuBar.Append(this.m_file);

//hBoxPrinci
//Définit si tous les composants doivent avoir la même taille et l'espacement entre les composants.
this.hBoxButton = new Gtk.HBox(true,2);
this.hBoxButton.PackStart(this.saveAs,false,false,2);
this.hBoxButton.PackStart(this.clear,true,true,2);
this.hBoxButton.PackStart(this.quit,false,false,2);

//hBoxPrinci
this.vBoxPrinci = new Gtk.VBox(false,0);
this.vBoxPrinci.PackStart(this.menuBar,false,false,2);
this.vBoxPrinci.PackStart(this.textView,true,true,2);
this.vBoxPrinci.PackStart(this.hBoxButton,false,false,10);

//MainForm
this.Add(this.vBoxPrinci);

this.Name = "MainForm";
this.DefaultWidth = 600;
this.DefaultHeight = 480;
this.DeleteEvent += new Gtk.DeleteEventHandler(this.WindowsDelete);
this.ShowAll();
}

private void WindowsDelete(object sender, Gtk.DeleteEventArgs e)
{
//On détruit la fenêtre principale
this.Destroy();
//On quitte le loopback principal
Application.Quit();
//On n'accepte plus les messages
e.RetVal = true;
}

public static void Main(string[] args)
{
Console.WriteLine("Lancement de LogView");

//Initialisation de GTKSharp
Application.Init();
new MainForm();
//Lancement du 'loopback' principal
Application.Run();

Console.WriteLine("Arret de LogView");
}

}
}

Voila le nouveau code de l'application après avoir placé tous les composants qui nous seront nécessaires.
Après compilation vous vous rendez compte que rien ne se passe quand vous cliquez sur un bouton ou sur un menu. Nous allons y remédier dans le prochain chapitre.

III-D - Le système de menu de GTK#

Le système de menu de GTK# est un peu complexe au début et peut-être déroutant au premier abord.
En effet, il faut commencer par placer un composant MenuBar qui sert de support au reste du menu.
Ensuite, il faut placer un MenuItem pour faire apparaitre le texte de la barre de menu. Afin d'avoir un menu, il faut insérer un « support » pour les MenuItems suivants.

Regardez le code précédent pour mieux comprendre le principe de fonctionnement.

IV - Gestion des évènements

La gestion des évènements se fait comme pour les applications Winform à l'aide des délégués et des évènements.
Si vous n'avez jamais vu ces notions, vous allez mieux comprendre en regardant le code.

//"Connexion" à un évènement d'un composant MenuItem.
this.m_exit.Activated += new System.EventHandler(this.exit_Click);

Si ces notions vous paraissent obscures, je vous invite à vous référer aux articles suivants :
Un article sur les délégués
Le tutoriel de MSDN sur les évènements
La relation entre les évènements et les délégués (MSDN)

La gestion des événements est donc assez simple somme toute, surtout si l'on ne cherche pas à savoir comment cela fonctionne derrière.

V - Le reste du code

Voyons maintenant le reste du code qui fera que notre application fait quand même quelque chose ;-)

V-A - Les boîtes de dialogue

Les boîtes de dialogue de GTK# ne sont pas très différentes de celles de .NET.
En effet les fonctions sont pratiquement les mêmes, il n'y a qu'un seul piège : elles ne se ferment pas toute seule.
En effet il faut que vous fassiez explicitement appel à Hide ou Destroy afin de les faire disparaître.

//fileSelection
this.fileSelection = new Gtk.FileSelection("Fichier à afficher ?");
this.fileSelection.Response += new Gtk.ResponseHandler(this.fileSelection_Select);
this.fileSelection.Run();
...
//On détruit la fenêtre afin qu'elle disparaisse et que les données soient réinitialisées
this.fileSelection.Destroy();

VI - (petite) grille de correspondance des composants entre GTK# et System.Windows.Forms

Dans cette partie je vais essayer de dresser une petite grille de correspondance entre les composants des deux systèmes.

Composants WinForm

Composants GTK#

Button

Button

TextBox

Entry

ComboBox

ComboBox (GTK# 2.0 seulement )

Label

Label

ListBox

Rien

TreeView

TreeView

ToolBar

ToolBar

MenuBar

MenuBar

MenuItem

MenuItem

Comme vous le voyez, il n'y a pas grande différence entre les deux systèmes de composants. En tout état de cause la monodoc vous sera très utile.

VII - La compilation

Bien, passons à la partie indispensable, mais pas très compliquée que représente la compilation.
Pour compiler un programme qui utilise GTK# il vous suffit de faire :

mcs -out:gtkSharpSample.exe -target:winexe -pkg:gtk-sharp-2.0 ./*.cs

Cette ligne de commande va compiler toutes les sources du répertoire courant (./*.cs), en utilisant le package GTK# en version 2.0 (-pkg:gtk-sharp-2.0 ), en fournissant un exécutable pour une application graphique (-target:winexe) et en nommant le fichier exécutable gtkSharpSample.exe.
Rien de bien compliqué.
Si vous avez un message d'erreur à la compilation vous indiquant que vous n'avez pas GTK# d'installé alors que vous êtes sûr de l'avoir installé, vérifiez que vous avez gtk-sharp-2.0.pc dans votre répertoire de pkg-config et/ou que votre variable d'environnement PKG_CONFIG_PATH pointe bien sur le répertoire qui le contient.

VIII - Ressources

Mon article sur Mono

Le site de Mono
Le site de GTK#

Le paquetage Gtk-Sharp sur le site gentoo
Un ftp avec le paquetage Gtk-Sharp pour la Mandriva LE 2005 [ftp://ftp.ciril.fr/pub/linux/mandrakelinux/official/2005/i586/media/contrib/]
Le site de mono avec les rpm pour la SuSE et la Red Hat

Le site de GTK+
Un site sur GTK+ en français

Le site de Mandriva
Le site de gentoo
Le site de SuSE
Le site de Red Hat

IX - Remerciements

Je tiens à remercier Gnux pour la relecture de l'article et ses conseils.