Outils pour utilisateurs

Outils du site


issue63:tuto_python

This time, we are going to take a short detour from our exploration of Android programming, and look at a new framework for GUI programming called Kivy. You’ll want to head over to http://kivy.org and download and install the package – before getting too far into this month’s installment. The Ubuntu installation instructions can be found at http://kivy.org/docs/installation/installation-ubuntu.html. First off, Kivy is an open source library that makes use of multi-touch displays. If that isn’t cool enough, it’s also cross-platform, which means that it will run on Linux, Windows, Mac OSX, IOS and Android. Now you can see why we are talking about this. But remember, for the most part, anything you code using Kivy, can run on any of the above platforms without recoding.

Cette fois-ci, nous allons dévier un peu de notre exploration de la programmation Android et regarder un nouvel environnement pour la programmation d'interfaces graphiques appelé Kivy. Vous pouvez aller sur http://kivy.org pour télécharger et installer le paquet, avant d'aller plus loin dans cet article. Les instructions d'installation pour Ubuntu sont ici : http://kivy.org/docs/installation/installation-ubuntu.html.

Tout d'abord, Kivy est une bibliothèque Open Source qui gère les écrans tactiles. Si ce n'est pas encore assez chouette, elle est aussi multi-plateforme, ce qui signifie qu'elle fonctionne sous Linux, Windows, Mac OSX, iOS et Android. Maintenant vous comprenez pourquoi nous en parlons. Mais rappelez-vous, la plupart du temps, tout ce que vous codez à l'aide de Kivy peut fonctionner sur n'importe laquelle des plateformes ci-dessus sans recodage.

Before we go too far, let me make a couple of statements. Kivy is VERY powerful. Kivy gives you a new set of tools to make your GUI programming. All that having been said, Kivy is also fairly complicated to deal with. You are limited to the widgets that they have provided. In addition, there is no GUI designer for Kivy, so you have to do a GREAT deal of pre-planning before you try to do anything complicated. Also remember, Kivy is continually under development so things can change quickly. So far, I haven’t found any of my test code that has broken by a new version of Kivy, but that’s always a possibility. Rather than jump in and create our own code this month, we’ll look at some of the examples that come with Kivy, and, next month, we’ll “roll our own”. Once you’ve unpacked Kivy into its own folder, use a terminal and change to that folder. Mine is in /home/greg/Kivy-1.3.0. Now change to the examples folder, then to the widgets folder. Let’s look at the accordion_1.py example. It’s very simple, but shows a really neat widget. Below is their code.

Avant d'aller trop loin, permettez-moi de faire quelques déclarations. Kivy est TRÈS puissant. Kivy vous procure un nouvel ensemble d'outils pour programmer des interfaces graphiques. Tout cela étant dit, Kivy est également assez compliqué à gérer. Vous êtes limité aux widgets qu'ils ont fournis. En outre, il n'existe pas de designer graphique pour Kivy et vous devez donc faire beaucoup de planification préalable avant d'essayer de faire des trucs compliqués. Rappelez-vous aussi que Kivy est constamment en développement et que les choses peuvent changer rapidement. Jusqu'à présent, je n'ai jamais eu de morceaux de mon code qui aient été cassés par une nouvelle version de Kivy, mais c'est toujours une possibilité.

Plutôt que de nous précipiter et de créer notre propre code ce mois-ci, nous allons examiner quelques-uns des exemples livrés avec Kivy et, le mois prochain, nous préparerons le nôtre.

Une fois que vous avez décompressé Kivy dans son propre dossier, utilisez un terminal et allez dans ce dossier. Le mien est dans /home/greg/Kivy-1.3.0. Maintenant, allez dans le dossier des exemples, puis dans le dossier widgets. Regardons l'exemple accordion_1.py.

Il est très simple, mais montre un widget très chouette. Ci-dessous, voici leur code.

As you can see, the first three lines are import statements. Any widget you use must be imported, and you must always import App from kivy.app. The next eight lines are the main application class. The class is defined, then a routine called build is created. You will almost always have a build routine somewhere in your Kivy programs. Next we set a root object from the Accordion widget. Next we create five AccordionItems and set their title. We then add ten labels with the text “Very big content”. We then add each label to the root widget (the Accordion) and then finally we return the root object. This, in essence, displays the root object in the window that Kivy creates for us. Finally we have the “if name” statement and then run the application. Go ahead and run it to see what it does.

Comme vous pouvez le voir, les trois premières lignes sont des déclarations d'importation. Tout widget que vous utilisez doit être importé et vous devez toujours importer App de kivy.app.

Les huit lignes suivantes sont la classe principale de l'application. La classe est définie, puis une routine appelée build est créée. Vous devrez presque toujours avoir une routine de construction (build) quelque part dans vos programmes Kivy. Ensuite nous définissons un objet racine du widget Accordéon. Ensuite, nous créons cinq éléments AccordionItems et définissons leurs titres. Nous ajoutons ensuite dix étiquettes avec le texte « contenu très grand ». Nous ajoutons ensuite chaque étiquette dans le widget racine (l'accordéon) et, enfin, nous retournons l'objet racine. C'est en substance ce qui affiche l'objet racine dans la fenêtre que crée Kivy. En dernier lieu, nous avons la déclaration « if name » puis exécutons l'application.

Allez-y, exécutez cet exemple pour voir ce qu'il fait.

You will see that in a moment or two, a window opens up with five vertical bars in it. Clicking on a bar causes it to open up revealing the ten labels. Of course, each bar has the same text in the ten labels, but you can figure out how to fix that. The Accordion widget can be used for any number of things, but the thing that has always jumped to my mind is for a configuration screen… each bar being a different configuration set. Next we’ll look at the textalign.py example. It’s not as “sexy” as the last one, but it’s a good example that gives you some important information for later on. Before we look at the code, run the program.

Dans quelques instants, vous verrez une fenêtre s'ouvrir avec cinq barres verticales à l'intérieur. En cliquant sur une barre, on provoque son ouverture ce qui révèle les dix étiquettes. Bien sûr, chaque barre a le même texte sur les dix étiquettes, mais vous êtes capable de changer cela.

Le widget Accordéon peut être utilisé pour toutes sortes de choses, mais la chose qui me vient toujours à l'esprit est un écran de configuration… chaque barre étant un ensemble distinct de configurations.

Ensuite, nous allons prendre l'exemple textalign.py. Il n'est pas aussi « sexy » que le précédent, mais c'est un bon exemple qui vous fournit des informations importantes pour la suite.

Avant de regarder le code, exécutez le programme.

What you should see is a label at the top of the window, a set of nine red boxes with text in a 3×3 grid, and four buttons along the bottom of the window. As you click (tap) each of the buttons, the alignment of the text within the red boxes will change. The main reason you would want to pay attention to this example is how to use and control some of the important widgets as well as how to change the alignment in your widgets, which is not completely intuitive. Above right is their code for this one. I’ll break it into pieces. First the import code (above right). Below is something special. They created a class with no code in it. I’ll discuss that in a few minutes: class BoundedLabel(Label): pass

Vous devriez voir une étiquette en haut de la fenêtre, un ensemble de neuf cases rouges avec du texte dans une grille 3×3 et quatre boutons le long du bas de la fenêtre. Lorsque vous cliquez (appuyez) sur chacun des boutons, l'alignement du texte dans les cases rouges changera. La raison principale pour laquelle il faut examiner cet exemple attentivement est qu'il vous montre comment utiliser et contrôler certains des widgets importants, ainsi que la façon de changer l'alignement de vos widgets, ce qui n'est pas totalement intuitif.

Le code de cet exemple se trouve ci-dessus à droite. Je vais le décortiquer. D'abord le code d'importation (en haut à droite).

Ci-dessous se trouve quelque chose de spécial. Ils ont créé une classe qui ne contient aucun code. Je vais en parler dans quelques minutes :

class BoundedLabel(Label):

pass

Next a class called “Selector” (below) is created: class Selector(FloatLayout): app = ObjectProperty(None) Now the Application class is created. Here the routine select is created. A GridLayout widget is created (called grid) which has 3 rows and 3 columns. This grid is going to hold the nine red boxes. for valign in ('bottom', 'middle', 'top'): for halign in ('left', 'center', 'right'):

Ensuite, une classe appelée « Selector » (ci-dessous) est créée :

class Selector(FloatLayout):

app = ObjectProperty(None)

Maintenant, la classe Application est créée.

C'est ici que la routine de sélection est créée. Un widget GridLayout est créé (appelée grid ou grille), qui dispose de 3 lignes et 3 colonnes. Cette grille va contenir les neuf cases rouges.

for valign in ('bottom', 'middle', 'top'):

for halign in ('left', 'center', 'right'):

Here we have two loops, one inner and one outer. label = BoundedLabel(text='V: %s\nH: %s' % (valign, halign), size_hint=(None, None), halign=halign, valign=valign) In the code above, an instance of the BoundedLabel widget is created, once for each of the nine red boxes. You might want to stop here and say “But wait! There isn’t a BoundedLabel widget. It just has a pass statement in it.” Well, yes, and no. We are creating an instance of a custom widget. As I said a little bit above, we’ll talk more about that in a minute. In the code block (top right, next page), we examine the variable ‘case’ which is passed into the select routine.

Ici nous avons deux boucles, l'une extérieure et l'autre intérieure.

label = BoundedLabel(text='V: %s\nH: %s' % (valign, halign),

size_hint=(None, None),

halign=halign, valign=valign)

Dans le code ci-dessus, une instance du widget BoundedLabel est créée, une fois pour chacune des neuf cases rouges. Vous voudrez peut-être m'arrêter là et dire : « Mais attendez ! Il n'y a pas de widget BoundedLabel. Il a juste une déclaration pass. » Eh bien, oui et non. Nous créons une instance d'un widget personnalisé. Comme je le disais un peu plus haut, nous en parlerons plus en détail dans un instant.

Dans le bloc de code (en haut à droite de la page suivante), nous examinons la variable « case », qui est passée à la routine de sélection.

Here, the grid is removed, to clear the screen. if self.grid: self.root.remove_widget(self.grid) The bind method here sets the size, and the grid is added to the root object. grid.bind(minimum_size=grid.setter('size')) self.grid = grid self.root.add_widget(grid) Remember in the last example I said that you will almost always use a build routine. Here is the one for this example. The root object is created with a FloatLayout widget. Next (middle right) we call the Selector class to create a Selector object, then it’s added to the root object, and we initialize the display by calling self.select(0).

Ici, on retire la grille pour effacer l'écran.

if self.grid:

self.root.remove_widget(self.grid)

La méthode bind ici définit la taille et la grille est ajoutée à l'objet racine.

grid.bind(minimum_size=grid.setter('size'))

self.grid = grid

self.root.add_widget(grid)

Rappelez-vous, dans le dernier exemple j'ai dit que vous devrez presque toujours utiliser une routine de construction. Voici celle de cet exemple. L'objet racine est créé avec un widget FloatLayout. Ensuite (au milieu à droite) nous appelons la classe Selector pour créer un objet de sélection, qui est ensuite ajouté à l'objet racine et on initialise l'affichage en appelant self.select(0).

Finally the application is allowed to run. TextAlignApp().run() Now, before we can go any further, we need to clear up a few things. First, if you look in the folder that holds the .py file, you’ll notice another file called textalign.kv. This is a special file that Kivy uses to allow you to create your own widgets and rules. When your Kivy application starts, it looks in the same directory for the .kv helper file. If it is there, then it loads it first. Here’s the code in the .kv file. This first line tells Kivy what minimum version of Kivy that must be used to run this app. #:kivy 1.0 Here the BoundedLabel widget is created. Each of the red boxes in the application is a BoundedLabel.

Enfin, l'application est autorisée à fonctionner.

TextAlignApp().run()

Maintenant, avant d'aller plus loin, nous devons éclaircir quelques petites choses. Tout d'abord, si vous regardez dans le dossier qui contient le fichier .py, vous remarquerez un autre fichier appelé textalign.kv. Ceci est un fichier spécial utilisé par Kivy pour vous permettre de créer vos propres widgets et règles. Lorsque votre application Kivy démarre, elle cherche dans le même répertoire le fichier d'aide .kv. S'il est présent, elle le charge en premier. Voici le code dans le fichier .kv.

Cette première ligne indique la version minimum de Kivy qui doit être utilisée pour exécuter cette application.

#:kivy 1.0

Ensuite le widget BoundedLabel est créé. Chacune des cases rouges dans l'application est un BoundedLabel.

Color sets the background color of the box to red (rgb: 1,0,0). The Rectangle widget creates a (you guessed it) rectangle. When we call the BoundedLabel widget in the actual application code, we are passing a label as the parent. The size and position (here in the .kv file) are set to whatever the size and position of the label are. Here (right, next page) the Selector widget is created. This is the four buttons that appear at the bottom of the window as well as the label across the top of the window. Notice that the label that makes up the title at the top of the window has a position (pos_hint) as top, has a height of 50 pixels and a font size of 16. Each of the buttons has an alignment for the text of center. The on_release statement is a bind-like statement so that, when the button is released, it calls (in this case) root.app.select with a case value. Hopefully, this is beginning to make sense now. You can see why Kivy is so powerful.

Color définit la couleur d'arrière-plan de la boîte à rouge (rgb: 1,0,0). Le widget Rectangle crée un rectangle (vous l'aurez deviné). Lorsque nous appelons le widget BoundedLabel dans le code de l'application, nous passons une étiquette en tant que parent. La taille et la position (ici dans le fichier .kv) sont réglées à la taille et la position de l'étiquette.

Ici (à droite sur la page suivante) le widget de sélection est créé. Ce sont les quatre boutons qui apparaissent au bas de la fenêtre ainsi que l'étiquette sur le haut de la fenêtre.

Remarquez que l'étiquette qui constitue le titre en haut de la fenêtre a une position (pos_hint) en haut, a une hauteur de 50 pixels et une taille de police de 16. Chacun des boutons a un texte aligné au centre. La déclaration on_release est une déclaration qui ressemble à « bind », qui fait que, lorsque le bouton est relâché, il appelle (dans ce cas) root.app.select avec la valeur « case ».

J'espère que tout commence à devenir plus clair maintenant. Vous pouvez voir pourquoi Kivy est si puissant.

Let’s talk for a moment about two widgets that I have passed over in the discussion of the application code, The GridLayout and the FloatLayout. The GridLayout is a parent widget that uses a row and column description to allow widgets to be placed in each cell. In this case, it is a 3×3 grid (like a Tic-Tac-Toe (or Naughts and Crosses) board). || || | | When you want to place a widget into a GridLayout, you use the add_widget method. Here lies a problem. You can’t specify which control goes into which grid cell other than the order in which you add them. In addition, each widget is added from left to right, top to bottom. You can’t have an empty cell. Of course, you can cheat. I’ll leave that up to you to figure out.

Examinons un instant deux widgets dont je n'ai pas parlé ci-dessus pendant la discussion du code de l'application, GridLayout et FloatLayout.

GridLayout est un widget parent qui utilise une description en ligne et colonne qui permet de placer les widgets dans chaque cellule. Dans ce cas, il s'agit d'une grille 3×3 (comme un plateau de Tic-Tac-Toe).

|| ||

|  |  

    Lorsque vous voulez placer un widget dans un GridLayout, vous utilisez la méthode add_widget. Il y a cependant un problème. Vous ne pouvez pas spécifier la cellule de la grille dans laquelle chaque commande sera placée autrement que par l'ordre dans lequel vous les ajoutez. En outre, chaque widget est ajouté de gauche à droite et de haut en bas. Vous ne pouvez pas avoir une cellule vide. Bien sûr, vous pouvez tricher. À vous de comprendre comment.

The FloatLayout widget seems to be just a parent container for other child widgets. I’ve glossed over a few points for now. My intent this time was simply to get you somewhat excited about the possibilities that Kivy has to offer. In the next couple of articles, we’ll continue to explore what Kivy has for us, how to use various widgets, and how to create an APK to publish our applications to Android. Until then, explore more of the examples in Kivy, and be sure to go to the documentation page for Kivy at http://kivy.org/docs/.

Le widget FloatLayout semble être juste un conteneur parent pour d'autres widgets enfants.

J'ai passé sous silence quelques points pour l'instant. Cette fois, mon intention était tout simplement de vous enthousiasmer par les possibilités qu'offre Kivy. Dans les prochains articles, nous allons continuer à explorer ce que Kivy peut nous apporter, comment utiliser divers widgets et comment créer un APK pour publier nos applications sur Android.

En atendant, explorez davantage les exemples de Kivy et, surtout, allez sur la page de documentation de Kivy : http://kivy.org/docs/.

issue63/tuto_python.txt · Dernière modification : 2012/09/15 12:32 de andre_domenech