252 lines
9.3 KiB
Markdown
252 lines
9.3 KiB
Markdown
---
|
||
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.
|
||
|
||
|
||
|
||
----
|
||
|
||

|