From b9e22325bb46e2611a73e54a3f0ade31800d1bd9 Mon Sep 17 00:00:00 2001 From: Sébastien Dailly Date: Fri, 9 May 2014 14:30:46 +0200 Subject: Moved to pelican 3.3 --- content/Informatique/ocaml_gtk.rst | 206 ------------------------------------- 1 file changed, 206 deletions(-) delete mode 100644 content/Informatique/ocaml_gtk.rst (limited to 'content/Informatique/ocaml_gtk.rst') diff --git a/content/Informatique/ocaml_gtk.rst b/content/Informatique/ocaml_gtk.rst deleted file mode 100644 index b124cb5..0000000 --- a/content/Informatique/ocaml_gtk.rst +++ /dev/null @@ -1,206 +0,0 @@ -.. -*- rst -*- -.. -*- coding: utf-8 -*- - -======================================= -Trois manière d'utiliser Gtk avec OCaml -======================================= - -:date: 2014-02-09 -:tags: ocaml, gtk -:summary: |summary| -:logo: static/images/ocaml/camel_75.jpg - -.. default-role:: literal - -.. figure:: |filename|/images/ocaml/camel_2.jpg - :figwidth: 150 - :figclass: floatleft - :alt: Pavement - - Image : `Kevin Botto`_ (creativecommons_) - -.. _Kevin Botto: http://www.flickr.com/photos/kevinbotto/3251157974/ -.. _creativecommons: http://creativecommons.org/licenses/by-nd/2.0/deed.fr - -|summary| - - -.. |summary| replace:: - Créer des interfaces Gtk pour OCaml peut se réveler compliquer. On trouve - beaucoup d'explications un peu confuses sur le net, et n'est pas facile de - trouver comment faire. - Je vous propose ici trois manières différentes en utilisants les différents - outils disponibles. - -Il est possible d'utiliser la bibliothèque Gtk à l'aide de la librairie -lablgtk_, qui fourni un binding pour l'ensemble de la bibliothèque. L'avantage -est de pouvoir fonctionner sur toutes les plateformes où gtk est disponible, et -de bénéficier d'une interface évoluée et agréable pour écrire son application. - -L'inconvénient réside dans la bibliothèque gtk : api très compliquée, -documentation confuse, bref on se retrouve rapidement face à des problèmes là -où l'on pensait pouvoir avancer sans difficulté. De plus, on est aujourd'hui -passé à gtk3 alors que `lablgtk` utilise toujours l'api de gtk2. Cela ne pose pas -de problème dans la compilation (la compatibilité est assurée), mais peut poser -problème lors de l'utilisation d'outils tels que `glade` (voir plus loin). - -.. _lablgtk: http://lablgtk.forge.ocamlcore.org/ - -Tout construire à la main -========================= - -C'est la première solution, qui demande de connaître Gtk : tous les objets sont -construits à la main, et le code décrit la manière de faire. L'avantage est que -le code ne dépend d'aucune ressource externes contrairement aux deux suivantes. -De plus on contrôle complètement la création de l'interface, on peut donc -choisir de paramétrer l'interface au lieu d'avoir une interface unique. Un -tutoriel complet est disponible sur le site d'`OCaml.org`_, je ne vais pas -le reprendre ici et vous encourage à le suivre. - -.. _ocaml.org: http://ocaml.org/learn/tutorials/introduction_to_gtk.html - -L'exemple est donné dans la console interactive. Si l'on souhaite le compiler -dans un module, il faut initialiser Gtk avant de lancer l'affichage : - -.. code-block:: ocaml - - GtkMain.Main.init (); - -Pour compiler un module, il est nécessaire de faire référence au package -`lablgtk2`. Voici un exemple pour compiler un fichier `hello.ml` : - -.. code-block:: console - - $ ocamlfind ocamlc -package lablgtk2 -I . -c hello.ml - -Maintenant il ne reste plus qu'à se plonger dans la documentation de gtk pour -construire son interface ! - -Utiliser Glade -============== - -Glade est une interface graphique permettant de construire son application en -plaçant les contrôles de manière visuelle. Elle génère un fichier XML qui -décrit l'interface et sera chargé par l'application pour construire -l'interface. Cela permet de gagner du temps et d'éviter d'écrire le code -nécessaire pour construire son interface, on se concentre sur les actions -à exécuter lorsque l'utilisateur interagit. - -.. image:: |filename|/images/glade.jpg - :class: center - :alt: Utilisation de glade. - - -Les XMLs générés par glade sont destinés à être utilisés avec gtk3. Or, -`lablgtk` utilise encore gtk2, il est donc nécessaire d'utiliser une conversion -pour pouvoir les charger par la suite. Voici une petite règle `make` qui se -charge de faire le travail : - -.. code-block:: make - - %.glade2: %.glade - cat $< | sed 's/interface/glade-interface/' | sed 's/object/widget/' | sed 's/GtkBox/GtkVBox/' > $@ - -Maintenant qu'on dispose d'un fichier au format glade2, on peut le charger dans -OCaml. - -Attention, lors de la compilation, il est nécessaire d'utiliser `libglade` pour -construire l'application, celle-ci est disponible dans la librairie -`lablgtk2.glade`. Voici donc un exemple de commande pour compiler un fichier -`hello.ml` : - -.. code-block:: console - - $ ocamlfind ocamlc -package lablgtk2.glade -I . -c hello.ml - -.. _gtkbuilder: https://developer.gnome.org/gtk3/3.4/GtkBuilder.html - -Charger le fichier xml ----------------------- - -Il s'agit de la solution la plus dynamique : on référence le fichier xml dans -le code, et l'interface se construit toute seule. Cette solution est présentée -sur le site de `developpez.com`_. L'exemple donné est toujours valide, il ne -faut pas oublier d'initialiser Gtk avec la commande suivante avant de lancer la -construction de l'interface : - -.. code-block:: ocaml - - GtkMain.Main.init (); - -L'inconvénient de cette méthode (du moins pour un développeur OCaml) est que -l'on est obligé de convertir de manière dynamique tous les objets présents dans -le XML. Il n'est pas possible de savoir au moment de la compilation si le code -que l'on va exécuter est bien valide. - -En effet, les objets chargés depuis le XML nous sont retournés sous la forme -widget gtk, qu'il faut convertir en Bouton, Menu via les méthodes appropriées -(`GtkWindow.Window.cast` par exemple). On n'est donc pas à l'abri d'avoir une -erreur lors du fonctionnement du programme, alors que celui-ci a pu compiler -sans problème. Je pense que lorsqu'on cherche à développer en OCaml, ce genre -de problème peut être rédhibitoire. - -.. _developpez.com: http://blog.developpez.com/damien-guichard/p7748/programmation-fonctionnelle/hello_developpez_avec_libglade_xml_1 - -De plus, rien ne garantie que le fichier XML ne va pas évoluer de manière -incompatible du code ; les deux étant distincts. - - -Utiliser lablgladecc2 ---------------------- - -Heureusement, la librairie `lablgtk2` nous fourni un petit utilitaire nommé -`lablgladecc2` qui va convertir un fichier xml glade2 en un fichier OCaml. On -dispose donc d'un chargement dynamique du fichier xml, mais en gardant un code -cohérent, qui détectera les erreurs dès la compilation. Il s'agit en quelque -sorte d'un moyen de combiner les deux solutions précédentes. - -On va ajouter une règle au makefile pour générer notre fichier OCaml : - -.. code-block:: make - - %.ml: %.glade2 - lablgladecc2 -embed $< > $@ - -Le fichier généré se compose d'une classe reprenant les différents composants -de notre interface, il ne nous reste plus qu'à réaliser les connexions, ainsi, -à partir d'un fichier glade nommé *gui* composé d'une fenêtre `window1`, d'un -bouton `button` et d'une entrée de menu, on peut créer le code suivant : - -.. code-block:: ocaml - - let gladecc () = - let window = new Gui.window1 () in - - window#button#connect#clicked (fun () -> prerr_endline "Ouch!"); - window#window1#connect#destroy GMain.quit; - window#imagemenuitem5#connect#activate GMain.quit; - - window#toplevel#show () - - let () = - GtkMain.Main.init (); - gladecc (); - GMain.Main.main () - - -l'objet `toplevel` est créé par `lablgladecc2` et correspond à la fenêtre -principale de notre objet. - -Dans cette chaîne de compilation, le fichier xml est écrit dans le programme -OCaml (il s'agit de la signification de l'option `-embed`), ainsi, le fichier -XML n'a pas besoin de figurer parmi les ressources de l'application. - -Conclusion -========== - -Trois manière de faire qui répondent à trois besoin différents, entre le tout -codé et le tout dynamique, il est possible de créer des interfaces graphiques -en utilisant les capacités du langage caml sur l'inférence de type et le -contrôle de l'ensemble de l'application. - -Pour ma part, je préfère la dernière solution, qui permet de conserver la -simplicité de `glade` combiné avec la force du langage OCaml. J'ai écrit cet -article suite à pas mal d'errance sur le net pour trouver les informations -nécessaires, j'espère que la documentation va évoluer par la suite et permettre -de faire ce genre de choses plus facilement… -- cgit v1.2.3