Initial commit
This commit is contained in:
251
documentation/10-graphical-ui.md
Normal file
251
documentation/10-graphical-ui.md
Normal file
@ -0,0 +1,251 @@
|
||||
---
|
||||
title: Faire sa première interface graphique
|
||||
author: Steve Kossouho
|
||||
---
|
||||
|
||||
# Faire sa première interface graphique avec Python
|
||||
|
||||
----
|
||||
|
||||
## Exemples d'outils pour les interfaces graphiques
|
||||
|
||||
Depuis la moitié des années 80, on a commencé à voir s'introduire dans le domaine public des
|
||||
ordinateurs livrés avec des interfaces graphiques, destinées à interagir simplement avec le système.
|
||||
Avec le temps, les outils de programmation se sont peaufinés, au point qu'à ce jour, il existe de
|
||||
très nombreux outils avancés de développement pour créer des interfaces graphiques, même avec Python.
|
||||
|
||||
Parmi eux, on rencontre fréquemment :
|
||||
|
||||
- [Qt](https://www.qt.io/) (PyQt ou PySide)
|
||||
- [GTK](https://www.gtk.org/) (Python-GTK)
|
||||
- [tkinter](https://docs.python.org/fr/3/library/tkinter.html) (bibliothèque standard)
|
||||
- [wxWidgets](https://www.wxwidgets.org/) (wxPython)
|
||||
|
||||
----
|
||||
|
||||
### Choix de la communauté
|
||||
|
||||
Parmi les choix disponibles pour créer des interfaces, les développeurs utilisent très fréquemment
|
||||
la bibliothèque Qt, de par la relative intuitivité de l'API que cette dernière propose. Également,
|
||||
elle est fournie avec de nombreuses applications très utiles pour concevoir ses applications, qui
|
||||
fonctionnent d'ailleurs assez bien sur de nombreux systèmes d'exploitation, comme Windows,
|
||||
Linux ou encore Mac OS.
|
||||
|
||||
----
|
||||
|
||||
### L'interface par défaut de Tkinter
|
||||
|
||||

|
||||
|
||||
(_Il est possible d'appliquer des thèmes qui imitent un thème, comme Win XP, Win 10, etc._)
|
||||
|
||||
----
|
||||
|
||||
### Exemple simple d'application Linux avec PySide
|
||||
|
||||

|
||||
|
||||
----
|
||||
|
||||
### Choix de bibliothèque pour la formation
|
||||
|
||||
Pour ce chapitre, nous allons utiliser la bibliothèque Qt. Avec Python, nous avons accès à plusieurs
|
||||
bibliothèques qui calquent l'API proposée par la bibliothèque originale en C++, telles que `PyQt` ou
|
||||
`PySide`.
|
||||
|
||||
Pour des raisons de prise en charge officielle (de contenu packagé, et probablement de licence),
|
||||
le choix se porte depuis quelques années sur `PySide`.
|
||||
|
||||
- [Documentation de PySide](https://wiki.qt.io/PySideDocumentation)
|
||||
- [Exemples PySide](https://wiki.qt.io/PySide_Example_Applications)
|
||||
|
||||
----
|
||||
|
||||
## PySide6 avec Python (sous Linux et Windows)
|
||||
|
||||
En principe, pour travailler avec PySide sous Windows et Linux, il vous suffira d'installer le
|
||||
paquet avec l'outil `pip`, aucun autre téléchargement ne semble être requis.
|
||||
|
||||
(Une intégration du thème des applications GTK dans PySide nécessite souvent d'utiliser le paquet
|
||||
`pyside` installable via le gestionnaire de paquets de votre distribution Linux, et d'installer
|
||||
également une bibliothèque pour Qt destinée à imiter les thèmes GTK.)
|
||||
|
||||
----
|
||||
|
||||
## Installer PySide avec pip
|
||||
|
||||
```{.bash .numberLines}
|
||||
pip install pyside6 # environ 200 Mo
|
||||
```
|
||||
|
||||
La commande installe la bibliothèque précompilée pour votre système d'exploitation, avec des programmes de gestion
|
||||
inclus (**Qt Designer**, **Qt Resource Compiler**, etc.).
|
||||
|
||||
----
|
||||
|
||||
## Écrire une fenêtre simple
|
||||
|
||||
Pour afficher sa première application fenêtrée avec PySide, nous **devons** suivre quelques directives :
|
||||
|
||||
- Créer un objet `QApplication` (singleton). Il gère notre application Qt.
|
||||
- Tous les widgets "vivront" automatiquement dans cet objet d'application.
|
||||
|
||||
```{.python .numberLines}
|
||||
from PySide6.QtWidgets import QApplication, QMainWindow
|
||||
|
||||
if __name__ == "__main__":
|
||||
application = QApplication()
|
||||
window = QMainWindow()
|
||||
window.show() # Affiche la fenêtre
|
||||
application.exec() # essayez sans cette ligne...
|
||||
```
|
||||
|
||||
----
|
||||
|
||||
## Concepts des interfaces graphiques Qt
|
||||
|
||||
Pour pouvoir parcourir plus en détail l'univers de **Qt**, il nous faut aborder certains concepts nécessaires pour un projet
|
||||
complet autour de la bibliothèque :
|
||||
|
||||
- `Signal` : représente un type d'événement disponible sur un widget, ex. _cliqué_, _texte modifié_, etc.
|
||||
- `Slot` : fonction exécutable lorsqu'un `Signal` est émis.
|
||||
- `Property` : attribut d'un widget défini sous forme de méthodes, ex. `QMainWindow.windowTitle`
|
||||
|
||||
----
|
||||
|
||||
## Concevoir graphiquement une fenêtre et l'utiliser avec Python
|
||||
|
||||
Il existe des outils graphiques pour concevoir vos fenêtres, et vous pouvez ensuite importer votre travail
|
||||
dans vos propres applications Python, ce qui vous permet de ne vous occuper que du code métier (ou presque).
|
||||
|
||||
Lorsque vous installez `PySide` avec `pip`, le package vous propose en ligne de commande d'utiliser
|
||||
l'application **Qt Designer**, un outil visuel qui vous aide à créer vos fenêtres et boîtes de dialogue.
|
||||
|
||||
```{.bash .numberLines}
|
||||
pyside6-designer & # lancer l'outil depuis un terminal… retirez le "&" sous Windows
|
||||
```
|
||||
|
||||
----
|
||||
|
||||
### Interface principale de Qt Designer
|
||||
|
||||

|
||||
|
||||
----
|
||||
|
||||
#### Zone principale
|
||||
|
||||
Lorsque vous utilisez Qt Designer, vous obtenez une interface **WYSIWYG** (What You See Is What You Get),
|
||||
vous permettant de configurer visuellement et précisément un widget (qu'il s'agisse d'une fenêtre ou d'autre chose).
|
||||
|
||||
Vous pouvez y sélectionner, redimensionner ou "reparenter" un widget. C'est beaucoup plus facile que
|
||||
de le faire à la main. Vous pouvez également y déposer de nouveaux widgets en effectuant un glisser-déposer depuis la **Boîte de widget**.
|
||||
|
||||
Note : Vous pouvez aussi générer du code Python via l'outil, mais il est assez inélégant.
|
||||
|
||||
----
|
||||
|
||||
#### Inspecteur d'objet
|
||||
|
||||
Le panneau d'inspecteur d'objet vous montre deux informations :
|
||||
|
||||
1. L'arborescence des widgets contenus dans votre fichier actuel;
|
||||
2. Chaque élément est affiché sur deux colonnes, d'abord le nom du widget (ex. `pushButton`), puis son type (ex. `QPushButton`).
|
||||
|
||||
Il peut être utile pour sélectionner facilement un widget, par exemple lorsque ce dernier est difficile à sélectionner
|
||||
avec la souris dans la zone d'aperçu.
|
||||
|
||||
----
|
||||
|
||||
#### Éditeur de propriétés
|
||||
|
||||
L'éditeur de propriétés est un panneau traditionnel (comme dans Visual Basic 4) affichant la liste des propriétés disponibles sur un widget, par exemple ses _dimensions_, la _police de caractères à utiliser_, le _texte du bouton_ etc…
|
||||
|
||||
Les propriétés sont souvent disponibles à la fois en lecture et en écriture, mais certaines peuvent n'exister
|
||||
que pour consulter un état d'un widget (lecture seule).
|
||||
|
||||
----
|
||||
|
||||
### Générer un script Python depuis Qt Designer
|
||||
|
||||
L'outil Qt Designer permet de générer des fichiers Python qui construisent votre fenêtre. Vous pouvez par la suite utiliser
|
||||
le code généré dans votre projet Python (même s'il y a mieux à faire).
|
||||
|
||||
TODO: Ajouter une capture d'écran
|
||||
|
||||
|
||||
----
|
||||
|
||||
### Charger un widget enregistré au format .ui
|
||||
|
||||
Les fichiers `.ui` générés par Qt Designer sont en réalité des fichiers XML indiquant l'arborescence de l'interface et
|
||||
les propriétés à définir sur les widgets.
|
||||
|
||||
Également, ces fichiers contiennent des informations supplémentaires, comme les fichiers de ressources associés, mais
|
||||
pour le cadre de la formation, nous ne sommes pas obligés de nous y intéresser. (ça peut attendre)
|
||||
|
||||
TODO: Promotion, Custom Signals et Slots, Ajout de propriétés etc.
|
||||
|
||||
```{.python .numberLines}
|
||||
from PySide6.QtUiTools import QUiLoader
|
||||
|
||||
# N'oubliez pas l'application, naturellement
|
||||
window = QUiLoader().load("fichier.ui") # QMainWindow
|
||||
```
|
||||
|
||||
----
|
||||
|
||||
## Interagir avec les contrôles
|
||||
|
||||
PySide propose un système simple de signaux (événements) et slots (fonctions cibles), qui permettent
|
||||
de réagir lorsque des événements se produisent sur des widgets.
|
||||
|
||||
Pour associer au clic sur un bouton l'exécution d'une fonction, nous devons utiliser
|
||||
une méthode `connect` sur une référence qui porte le nom d'un événement, par exemple `clicked` :
|
||||
|
||||
```{.python .numberLines}
|
||||
from PySide6.QtWidgets import QPushButton
|
||||
|
||||
def some_function_reference():
|
||||
pass
|
||||
|
||||
button = QPushButton()
|
||||
button.clicked.connect(some_function_reference)
|
||||
```
|
||||
|
||||
Notez que PyCharm ne peut pas autocompléter `connect` à cause de la nature de la bibliothèque
|
||||
(écrite en C++, avec des _stubs_ incomplets pour Python).
|
||||
Ce problème semble ne pas pouvoir être résolu ni du côté de **JetBrains**, ni du côté de **Microsoft**.
|
||||
Il semble qu'il pourrait être résolu du côté de **Qt**, qui refuse de corriger ses stubs Python…
|
||||
|
||||
----
|
||||
|
||||
## Qt Designer : mise en page adaptée au redimensionnement de fenêtre
|
||||
|
||||
Sous Qt Designer (ou QtCreator), aucun moyen simple n'a l'air disponible pour associer un layout
|
||||
au widget central d'une fenêtre (c'est-à-dire, un widget de mise en page qui possède toujours les mêmes
|
||||
dimensions que la fenêtre)…
|
||||
|
||||
Ça n'est pas intuitif, mais y parvenir est beaucoup plus simple qu'il n'y paraît.
|
||||
|
||||
----
|
||||
|
||||

|
||||
|
||||
----
|
||||
|
||||
- Vous pouvez cliquer droit dans un espace vide de la fenêtre, et ajouter un layout au **widget central** :
|
||||
|
||||
- Allez sur le menu contextuel `Mettre en page` (ou `Lay out`);
|
||||
- Puis choisissez le layout utilisé pour le widget central (généralement `QGridLayout`);
|
||||
- Tous les éléments qui étaient présents dans le widget central vont se disposer dans le nouveau layout.
|
||||
|
||||
- Vous pouvez aussi sélectionner le widget central dans l'inspecteur puis cliquer sur un bouton de layout dans la barre d'outils de l'application.
|
||||
|
||||
Le layout étant associé au widget central de la fenêtre, il se redimensionnera avec la fenêtre.
|
||||
|
||||
|
||||
|
||||
----
|
||||
|
||||

|
Reference in New Issue
Block a user