Initial commit
This commit is contained in:
146
documentation/10-graphical-ui-extra.md
Normal file
146
documentation/10-graphical-ui-extra.md
Normal file
@ -0,0 +1,146 @@
|
||||
---
|
||||
title: Interfaces graphiques avec Pyside
|
||||
author: Steve Kossouho
|
||||
---
|
||||
|
||||
# Développer avec Pyside et Qt Designer
|
||||
|
||||
----
|
||||
|
||||
## Fichiers .ui et utilisation avec Python
|
||||
|
||||
Nous avons vu précedemment comment concevoir graphiquement des fenêtres dans l'outil Qt Designer,
|
||||
puis comment les exploiter dans notre code Python. Nous avons d'abord utilisé la classe `QUiLoader`
|
||||
et récupéré un objet de type `QWidget` (généralement de type `QMainWindow` précisément).
|
||||
|
||||
```python
|
||||
from PySide6.QtUiTools import QUiLoader
|
||||
from PySide6.QtWidgets import QApplication
|
||||
|
||||
def button_slot():
|
||||
"""Fonction utilisée comme slot."""
|
||||
pass
|
||||
|
||||
if __name__ == '__main__':
|
||||
app = QApplication()
|
||||
window = QUiLoader().load("file.ui")
|
||||
button = window.button
|
||||
button.clicked.connect(button_slot)
|
||||
window.show()
|
||||
...
|
||||
app.exec()
|
||||
```
|
||||
|
||||
----
|
||||
|
||||
### Problème de l'approche "non objet"
|
||||
|
||||
Cette approche simple ne permet malheureusement pas de profiter de certaines fonctionnalités
|
||||
essentielles. Par exemple, il n'est pas possible de définir des _slots_ via de simples fonctions dans lesquels
|
||||
il serait possible de retrouver un widget qui a généré un _signal_.
|
||||
|
||||
La raison principale à cette catégorie de problèmes provient du fait que l'application Qt est gérée via l'objet
|
||||
`QApplication` dans un thread distinct. Ce thread n'est pas en mesure de transmettre certaines références au processus
|
||||
principal de votre programme, notamment les références d'objets générant un signal.
|
||||
|
||||
----
|
||||
|
||||
Le seul moyen correct de procéder (assez mal documenté) afin que votre code gérant vos widgets soit connecté au thread
|
||||
de l'application Qt : Coder la gestion de votre fenêtre dans une classe héritant au moins d'une classe de la bibliothèque
|
||||
Qt (ex. `QObject`). Hériter d'une telle classe vous offre d'ailleurs une méthode essentielle pour retrouver une référence
|
||||
d'objet ayant généré un signal : `sender()`
|
||||
|
||||
----
|
||||
|
||||
Voici un exemple de code correct important une conception graphique d'un fichier .ui :
|
||||
|
||||
```python
|
||||
from PySide6.QtCore import QObject, Slot
|
||||
from PySide6.QtUiTools import QUiLoader
|
||||
from PySide6.QtWidgets import QApplication, QMainWindow, QPushButton, QWidget
|
||||
|
||||
class WindowManager(QObject):
|
||||
"""Classe gérant l'interface graphique et contenant des slots."""
|
||||
window: QMainWindow | QWidget = None
|
||||
button: QPushButton = None
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
# Ligne nécessaire pour exécuter l'initiation du QObject
|
||||
super().__init__(*args, **kwargs)
|
||||
self.window = QUiLoader().load("fichier.ui")
|
||||
self.button = getattr(self.window, "button")
|
||||
# Configurer le clic sur le bouton peut être configuré dans Designer
|
||||
self.button.clicked.connect(self.button_clicked)
|
||||
|
||||
@Slot() # marquer correctement la méthode comme slot
|
||||
def button_clicked(self):
|
||||
"""Slot du clic sur le bouton."""
|
||||
print(self.sender())
|
||||
|
||||
if __name__ == '__main__':
|
||||
application = QApplication()
|
||||
manager = WindowManager()
|
||||
manager.window.show()
|
||||
application.exec()
|
||||
```
|
||||
|
||||
----
|
||||
|
||||
Dans l'exemple précédent, plusieurs éléments importants ont été rigoureusement respectés :
|
||||
|
||||
- La classe de gestion de l'interface et des slots hérite de `QObject` au moins;
|
||||
- les slots sont décorés par la classe `Slot`, qui possède une méthode `__call__` renvoyant un décorateur (parenthèses nécessaires);
|
||||
|
||||
----
|
||||
|
||||
## Utiliser des widgets personnalisés dans Designer
|
||||
|
||||
Supposons que vous avez rédigé du code pour créer votre propre widget (soit personnellement dessiné soit composé d'autres sous-widgets).
|
||||
Vous souhaitez utiliser Qt Designer pour concevoir votre interface, faisant usage dudit widget.
|
||||
|
||||
Malheureusement pour vous, seuls les widgets standard proposés par la bibliothèque Qt seront disponibles dans la boîte à outils
|
||||
de Qt Designer. Heureusement, il est possible de personnaliser votre conception pour intégrer vos propres classes de widgets.
|
||||
Pour cela vous devez insérer dans l'interface un widget duquel hérite votre classe personnalisée (ex. `QFrame`) puis le "**promouvoir**".
|
||||
|
||||
----
|
||||
|
||||
Pour cela, sélectionnez votre widget dans l'interface d'aperçu ou dans l'explorateur d'objet avec un clic droit.
|
||||
Cliquez ensuite sur l'option `Promouvoir en…`. Une boîte de dialogue listant les widgets déjà promus s'affichera et vous proposera
|
||||
de promouvoir le widget que vous venez de sélectionner.
|
||||
|
||||

|
||||
|
||||
----
|
||||
|
||||
Vous devez sélectionner la classe de widget de base (probablement celle déjà utilisée pour le widget à promouvoir),
|
||||
puis indiquer le nom de la classe de widget à utiliser à l'exécution. Le nom du fichier d'en-tête n'est utilisé que pour
|
||||
le langage C++, donc vous pouvez y saisir un point (`.`).
|
||||
|
||||
----
|
||||
|
||||
Une fois le fichier .ui regénéré, il vous faudra configurer votre objet `QUiLoader` pour y enregistrer les classes de
|
||||
widgets personnalisées :
|
||||
|
||||
```python
|
||||
from PySide6.QtUiTools import QUiLoader
|
||||
from mymodule import MyWidgetClass
|
||||
|
||||
loader = QUiLoader()
|
||||
# Register custom widget class so that the promoted widget works.
|
||||
loader.registerCustomWidget(MyWidgetClass)
|
||||
widget = loader.load("fichier.ui")
|
||||
```
|
||||
|
||||
Au chargement du fichier XML, les références du nom de classe généreront correctement les instances du type approprié.
|
||||
Notez que si votre classe de widget définit des propriétés supplémentaires par rapport à la classe dont elle hérite,
|
||||
vous pouvez les ajouter et les initialiser dans le panneau de l'_éditeur de propriétés_ de Qt Designer.
|
||||
|
||||
----
|
||||
|
||||
## CSS dans les widgets
|
||||
### Propriétés CSS
|
||||
### Appliquer correctement son CSS
|
||||
### Appliquer depuis un fichier
|
||||
## Ressources
|
||||
### Créer une ressource
|
||||
### Compiler une ressource
|
Reference in New Issue
Block a user