Modifications

Sauter à la navigation Sauter à la recherche
6 963 octets ajoutés ,  15 août 2016 à 14:37
aucun résumé de modification
Ligne 1 : Ligne 1 :  
{{RASP-PYGAME-GUI-NAV}}
 
{{RASP-PYGAME-GUI-NAV}}
 +
 +
== Installation ==
 +
Nous allons améliorer notre interface utilisateur en ajoutant le framework de widget [https://github.com/fictorial/pygameui PygameUI].
 +
 +
Un peu de vocabulaire:
 +
* Widget: Widget certainement dérivé de gadget (''plus connu''). Est un composant d'interfae graphique (bouton, barre de défilement, zone de saisie, libellé) avec lequel il est possible d'interagir.
 +
* Framework: c'est un ensemble cohérent de composants logiciels qui sert de fondation au développement de logiciels plus avancés. L'avantage d'un framework est de vous faire gagné beaucoup de temps puisque des développeurs se sont acharnés à réaliser d'une fondation (travail déjà fait) sur-laquelle vous pourrez bâtir (plus rapidement) vos propres éléments logiciels.
 +
 +
Faite une mise-à-jour de votre distribution:
 +
 +
<syntaxhighlight lang="bash">
 +
sudo easy_install -U distribute
 +
</syntaxhighlight>
 +
 +
Installer PygameUI:
 +
 +
<syntaxhighlight lang="bash">
 +
sudo pip install pygameui
 +
</syntaxhighlight>
 +
 +
PygameUI utilise la font IMO par défaut, une font plutôt moche! Vous vous désirez utiliser une autre font, il vous faudra simplement copier une série de font "True Type" dans le répertoire des ressources de pygameui.
 +
 +
Vous pourrez identifier tous les fichiers ttf déjà disponibles sur votre Raspberry Pi à l'aide de la commande suivante:
 +
 +
<syntaxhighlight lang="bash">
 +
sudo find / -type f  -name '*.ttf'
 +
</syntaxhighlight>
 +
 +
Maintenant, vous pouvez copier une font regular (''normale'') et une font bold (''gras'') à la place des fonts existantes dans le répertoire.
 +
 +
Vous pourriez avoir besoin de faire un backup des fichiers originaux... juste au cas où.
 +
 +
<syntaxhighlight lang="bash">
 +
cd /usr/local/lib/python2.7/dist-packages/pygameui/resources/fonts
 +
sudo mv bold.ttf bold.old
 +
sudo mv regular.ttf regular.old
 +
sudo cp /usr/share/fonts/truetype/freefont/FreeSans.ttf regular.ttf
 +
sudo cp /usr/share/fonts/truetype/freefont/FreeSansBold.ttf bold.ttf
 +
</syntaxhighlight>
 +
 +
Dans cet exemple, nous allons contrôler les GPIO #17 et #4 comme avant mais en utilisant un nouveau Framework.
 +
 +
{{ADFImage|RASP-PYGAME-GUI-PygameUI-GPIO-00.jpg}}
 +
 +
Le rendu des widgets et gestion des événements écrans seront pris en charge par PygameUI. La classe {{fname|PiTft}} définit les boutons à dessiner sur l'écran et l'événement click (''clic'') à exécuter lorsque le bouton est pressé.
 +
 +
{{ADFImage|RASP-PYGAME-GUI-PygameUI-GPIO-01.png}}
 +
 +
== Démarrer ==
 +
Au début du script, nous importons la bibliothèque {{fname|pygameui}}. Comme nous l'utiliserons régulièrement dans le code, nous lui associons l'alias {{fname|ui}} (plus sympa et plus court à taper).
 +
 +
L'autre ajout important ici est [https://docs.python.org/2/library/logging.html logging]. Il est utile de mettre une trace (''logging'') en place Lorsque l'on utilise plusieurs bibliothèques et frameworks pour façon à voir les sorties dans un fichier (ou dans ce cas, sur une console). Il est également possible de définir le logger en mode {{fname|DEBUG}} de manière à voir ce qui se passe sous votre code et effectuer des corrections si nécessaire.
 +
 +
<syntaxhighlight lang="python">
 +
import pygame
 +
import os
 +
import pygameui as ui
 +
import logging
 +
import RPi.GPIO as GPIO
 +
 +
# Configurer les GPIOs comme sortie (OUTPUT) - Seuls 4 et 17 sont disponibles
 +
GPIO.setmode(GPIO.BCM)
 +
GPIO.setup(4, GPIO.OUT)
 +
GPIO.setup(17, GPIO.OUT)
 +
 +
# Format de trace
 +
# Definition d'un flux pour le logger (flux associé à la console)
 +
log_format = '%(asctime)-6s: %(name)s - %(levelname)s - %(message)s'
 +
console_handler = logging.StreamHandler()
 +
console_handler.setFormatter(logging.Formatter(log_format))
 +
# Definir la trace
 +
logger = logging.getLogger()
 +
logger.setLevel(logging.DEBUG)
 +
logger.addHandler(console_handler) # Sortie trace sur console
 +
 +
os.putenv('SDL_FBDEV', '/dev/fb1')
 +
os.putenv('SDL_MOUSEDRV', 'TSLIB')
 +
os.putenv('SDL_MOUSEDEV', '/dev/input/touchscreen')
 +
</syntaxhighlight>
 +
 +
== Définition de l'interface utilisateur ==
 +
Pour quelques astuces sur l'utilisation des widgets avec le framework vous pouvez consulter le script [https://github.com/fictorial/pygameui/blob/master/bin/pygameui-kitchensink.py kitchen sink (pygameui-kitchensink.py)] .
 +
 +
Le principe de base c'est qu'il faut définir une classe qui hérite de {{fname|ui.Scene}} et dans la méthode {{fname|__init__}} vous définissez tous les widgets. Une ''Scene'' est une fenêtre compllète, dans notre cas c'est l'afficheur en entier (320,240).
 +
 +
La poisition et la taille de chaque bouton est défini en utilisant {{fname|ui.Rect}} et un libellé (''text label'') est également disponible. Un gestionnaire d'événement {{fname|on_clicked}} (aussi appelé "''handler''" en anglais) est alors assigné - ce ''handler'' est appelé lorsque l'on clique sur le bouton. Dans notre cas, le ''handler'' est la méthode {{fname|gpi_button}} .
 +
 +
La méthode {{fname|gpi_button}} vérifie simplement le libellé du bouton qui à été clické pour déterminer le GPIO qu'il faut allumer ou éteindre.
 +
 +
<syntaxhighlight lang="python">
 +
MARGIN = 20
 +
 +
class PiTft(ui.Scene):
 +
    def __init__(self):
 +
        ui.Scene.__init__(self)
 +
 +
        self.on17_button = ui.Button(ui.Rect(MARGIN, MARGIN, 130, 90), '17 on')
 +
        self.on17_button.on_clicked.connect(self.gpi_button)
 +
        self.add_child(self.on17_button)
 +
 +
        self.on4_button = ui.Button(ui.Rect(170, MARGIN, 130, 90), '4 on')
 +
        self.on4_button.on_clicked.connect(self.gpi_button)
 +
        self.add_child(self.on4_button)
 +
 +
        self.off17_button = ui.Button(ui.Rect(MARGIN, 130, 130, 90), '17 off')
 +
        self.off17_button.on_clicked.connect(self.gpi_button)
 +
        self.add_child(self.off17_button)
 +
 +
        self.off4_button = ui.Button(ui.Rect(170, 130, 130, 90), '4 off')
 +
        self.off4_button.on_clicked.connect(self.gpi_button)
 +
        self.add_child(self.off4_button)
 +
 +
    def gpi_button(self, btn, mbtn):
 +
        logger.info(btn.text)
 +
       
 +
        if btn.text == '17 on':
 +
            GPIO.output(17, False)
 +
        elif btn.text == '4 on':
 +
            GPIO.output(4, False)
 +
        elif btn.text == '17 off':
 +
            GPIO.output(17, True)
 +
        elif btn.text == '4 off':
 +
            GPIO.output(4, True)
 +
 +
ui.init('Raspberry Pi UI', (320, 240))
 +
pygame.mouse.set_visible(False)
 +
ui.scene.push(PiTft())
 +
</syntaxhighlight>
 +
 +
== La boucle principale ==
 +
C'est le point clé du programme. La boucle principale de votre programe est maintenant pris en charge par pygameui. Le [https://en.wikipedia.org/wiki/Inversion_of_control contrôle du programme est ''inversé''] - Nous fournissons à pygameui le code a appeler lorsque certaines actions utilisateurs arrivent.
 +
 +
La boucle principale de pygameui est démarré à l'aide de cette dernière ligne de code:
 +
 +
<syntaxhighlight lang="bash">
 +
ui.run()
 +
</syntaxhighlight>
 +
 +
Comme d'habitude, vous pouvez exécuter ce programme depuis le projet pygamelcd :
 +
 +
<syntaxhighlight lang="bash">
 +
sudo python test4.py
 +
</syntaxhighlight>
    
{{RASP-PYGAME-GUI-TRAILER}}
 
{{RASP-PYGAME-GUI-TRAILER}}
29 918

modifications

Menu de navigation