Aller au contenu principal

Découvrir PySide

Créer sa première fenêtre avec PySide.

Notions théoriques

PySide (aussi appelé Qt for Python) est le binding officiel du framework Qt pour le langage Python.

PySide permet de créer des interfaces graphiques (GUI) modernes, performantes et multiplateformes.

info
  • Installation : Contrairement à Tkinter, PySide n'est pas inclus dans la bibliothèque standard. Il faut l'installer via pip.
  • Version : Ce tutoriel utilise PySide6 (la version actuelle compatible avec Qt 6).
  • Multiplateforme : Une application PySide tourne sur Windows, macOS et Linux sans modification du code.

Créer une interface avec PySide repose toujours sur ces étapes fondamentales :

  1. Importer les modules nécessaires (QApplication, QWidget, etc.)
  2. Créer l'application ( QApplication )
  3. Créer la fenêtre principale ( QWidget ou QMainWindow )
  4. Ajouter des widgets (boutons, étiquettes, zones de texte…)
  5. Organiser les widgets avec un gestionnaire de mise en page (Layout)
  6. Connecter les signaux (events) à des slots (fonctions)
  7. Afficher la fenêtre et lancer la boucle principale (exec)
import sys
from PySide6.QtWidgets import QApplication, QWidget

La classe centrale pour démarrer est QApplication. Et la fenêtre principale est souvent une instance de QWidget ou QMainWindow.

Voici un exemple minimaliste qui crée une fenêtre vide :

app = QApplication(sys.argv) # Gestion des arguments et paramètres système
fenetre = QWidget()
fenetre.setWindowTitle("Ma première fenêtre")
fenetre.resize(400, 300) # largeur, hauteur


astuce

Dans PySide, on utilise souvent resize() au lieu de geometry(), et les dimensions sont passées comme deux entiers distincts.


Les widgets les plus courants

  • QLabel → affiche du texte ou une image
  • QPushButton → bouton cliquable
  • QLineEdit → zone de saisie d’une ligne
  • QTextEdit → zone de saisie multiligne
  • QCheckBox → case à cocher
  • QRadioButton → bouton radio (choix exclusif)
  • QFrame / QWidget → conteneur pour regrouper des widgets

Les gestionnaires de mise en page (Layouts)

PySide ne utilise pas pack() ou grid() comme méthodes des widgets. Il utilise des objets Layout que l'on ajoute à un conteneur. Les widgets sont ensuite ajoutés à ce layout.

Les 3 layouts principaux sont :

  • QVBoxLayout (Vertical)
  • QHBoxLayout (Horizontal)
  • QGridLayout (Grille)

1. Le layout Vertical (QVBoxLayout)

Empile les widgets les uns sous les autres.

layout = QVBoxLayout()
layout.addWidget(label)
layout.addWidget(bouton)
fenetre.setLayout(layout)
astuce

C'est l'équivalent direct de pack() côté Tkinter, mais plus explicite.

2. Le layout Horizontal (QHBoxLayout)

Aligne les widgets de gauche à droite.

layout = QHBoxLayout()
layout.addWidget(label)
layout.addWidget(bouton)
fenetre.setLayout(layout)

3. Le layout Grille (QGridLayout)

Tableau avec lignes et colonnes.

layout = QGridLayout()
layout.addWidget(label, 0, 0) # row, column
layout.addWidget(entry, 0, 1)
fenetre.setLayout(layout)
astuce

Les layouts PySide gèrent automatiquement le redimensionnement de la fenêtre, ce qui rend l'interface "responsive" sans effort supplémentaire.

attention

Il faut toujours appeler setLayout() sur le conteneur (la fenêtre ou un widget parent) pour que le layout soit actif.


Associer une action à un bouton (Signaux et Slots)

PySide utilise un mécanisme puissant appelé Signals et Slots. Un signal est émis (ex: clic) et est connecté à une fonction (slot).

def saluer():
print("Bonjour !")

bouton = QPushButton("Dire bonjour")
bouton.clicked.connect(saluer)
info

On connecte le signal .clicked du bouton à la fonction. Contrairement à Tkinter, on met des parenthèses vides saluer() lors de la définition de la fonction, mais pas lors du connect.


Modifier un widget après sa création

On utilise des "setters" (méthodes commençant par set) ou la feuille de style (CSS-like) :

label.setText("Nouveau texte")
label.setStyleSheet("color: darkblue; background-color: lightyellow; font-weight: bold;")

Accéder aux données des widgets

Contrairement à Tkinter qui utilise souvent des variables spéciales (StringVar), PySide préfère l'accès direct aux propriétés des widgets via des méthodes get (souvent sans préfixe "get").

Exemple classique :

# QLineEdit
texte = line_edit.text() # lecture
line_edit.setText("Alice") # écriture

# QCheckBox
est_coche = checkbox.isChecked()
remarque

Bien qu'il existe un système de variables plus complexe, la lecture directe via .text() ou .isChecked() est la méthode la plus courante pour des applications simples.


Exemple pratique

Voici un exemple minimaliste qui utilise un QVBoxLayout.

Les layouts sont la méthode standard en PySide : ils gèrent la taille et la position automatiquement.

import sys
from PySide6.QtWidgets import QApplication, QWidget, QLabel, QVBoxLayout

# Création de l'application (obligatoire)
app = QApplication(sys.argv)

# Création de la fenêtre principale
fenetre = QWidget()
fenetre.setWindowTitle("Exemple pratique")

# Création du layout vertical
layout = QVBoxLayout()

# Création d'un texte (Label)
etiquette = QLabel("Bonjour à tous !")
etiquette.setStyleSheet("font-size: 16px;") # Feuille de style CSS

# Ajout du widget au layout
layout.addWidget(etiquette)

# Application du layout à la fenêtre
fenetre.setLayout(layout)

# Affichage de la fenêtre et lancement de la boucle
fenetre.show()
sys.exit(app.exec())

Ce que ce code réalise :

  1. L'initialisation de QApplication.
  2. La création de la fenêtre racine (QWidget).
  3. La création d'un layout (QVBoxLayout) pour organiser les éléments.
  4. La création d'un widget simple (QLabel).
  5. L'ajout du widget au layout.
  6. L'assignation du layout à la fenêtre.
  7. L'exécution de la boucle d'événements (app.exec()).

Test de mémorisation/compréhension


Quelle commande permet d'installer la bibliothèque PySide6 ?


Quel est l'équivalent de `command=` en Tkinter pour lier une action à un bouton en PySide ?


Quelle classe fondamentale doit être instanciée en tout premier dans un script PySide ?


Quel widget PySide correspond au `Entry` de Tkinter (saisie d'une ligne) ?


Comment modifie-t-on le texte d'un `QLabel` existant ?


Quel gestionnaire de layout empile les widgets verticalement ?


Quelle méthode permet d'appliquer un layout créé à un widget conteneur (comme la fenêtre) ?


Comment récupère-t-on le texte saisi par l'utilisateur dans un `QLineEdit` nommé `saisie` ?


En PySide, quel mécanisme permet à un widget de communiquer une action (ex: clic) à une fonction ?


Quelle méthode doit-on appeler sur la fenêtre pour qu'elle devienne visible à l'écran ?


Quel est l'avantage principal de l'utilisation des layouts (QVBoxLayout, etc.) par rapport au positionnement absolu ?


Quel widget utilise-t-on pour créer une case à cocher en PySide ?


Quel est le rôle de `sys.exit(app.exec())` à la fin d'un script PySide ?


Comment définir une feuille de style simple (ex: couleur rouge) sur un bouton ?



TP pour réfléchir et résoudre des problèmes

1. Créer un dossier tp-pyside-demo et y ajouter un fichier main.py

mkdir tp-pyside-demo
cd tp-pyside-demo
touch main.py

2. Créer un environnement virtuel Python et l’activer :

python -m venv venv
source venv/bin/activate # Sur Windows : venv\Scripts\activate

3. Installer PySide6 :

PySide n'est pas inclus par défaut, il faut l'installer via pip.

pip install PySide6

Si la commande s'exécute sans erreur, vous êtes prêt. Vous pouvez vérifier avec python -c "import PySide6; print(PySide6.__version__)".

4. Ouvrir main.py avec Visual Studio Code et écrire le code pour importer PySide et créer la fenêtre principale

import sys # Importation des modules nécessaires
from PySide6.QtWidgets import QApplication, QWidget # Importation des classes nécessaires

# --------------------------------------
# Création de l'application et de la fenêtre
# --------------------------------------
app = QApplication(sys.argv) # Gestion des arguments et paramètres système
fenetre = QWidget() # Création de la fenêtre principale
fenetre.setWindowTitle("Ma première fenêtre") # Titre de la fenêtre
fenetre.resize(400, 250) # largeur, hauteur

fenetre.show() # Affichage de la fenêtre
sys.exit(app.exec()) # Boucle principale de l'application

Le fichier main.py sera rempli plus tard.

5. Lancer le script pour vérifier que la fenêtre s’affiche correctement :

python main.py

Si une petite fenêtre fenêtre vide avec le titre "Ma première fenêtre" s'affiche, c’est que tout est bon.

Si l'erreur ModuleNotFoundError: No module named 'PySide6's'affiche

Pour résoudre l'erreur ModuleNotFoundError: No module named 'PySide6', il suffit d'installer PySide6 avec la commande :

pip install PySide6

Installation de PySide6

6. Ajouter une étiquette (QLabel) avec le texte "Bienvenue dans PySide !"

Insérez l'import suivant au début du fichier main.py :

from PySide6.QtWidgets import QLabel, QVBoxLayout
from PySide6.QtCore import Qt

Insérez le code suivant avant fenetre.setLayout(layout), pour créer un layout vertical et y ajouter le label :

# Création du layout
layout = QVBoxLayout()

# Création du Label
etiquette = QLabel("Bienvenue dans PySide !")
etiquette.setStyleSheet("font-size: 16px; font-weight: bold;")
etiquette.setAlignment(Qt.AlignCenter) # Centre le texte dans le label

# Ajout du Label au layout
layout.addWidget(etiquette)

# Application du layout à la fenêtre
fenetre.setLayout(layout)

remarque

Ici, nous devons d'abord créer un QVBoxLayout, y ajouter le label, puis appliquer ce layout à la fenêtre.

7. Ajouter une zone de saisie (QLineEdit) pour que l’utilisateur puisse entrer son prénom

Ajoutez l'import QLineEdit et insérez le code suivant après l'ajout du label (toujours avant fenetre.setLayout(layout) :

from PySide6.QtWidgets import QLineEdit

# Création de la zone de saisie
saisie = QLineEdit() # Zone de saisie de texte
saisie.setPlaceholderText("Entrez votre prénom ici...") # Texte grisé par défaut
saisie.setAlignment(Qt.AlignCenter) # Centre le texte dans la zone de saisie

# Ajout de la zone de saisie au layout
layout.addWidget(saisie)

remarque

En PySide, setPlaceholderText permet d'afficher un texte indicatif dans une zone de saisie lorsque celle-ci est vide.

8. Ajouter un bouton (QPushButton) avec le texte "Valider" qui affiche une boîte de dialogue de bienvenue personnalisée

Ajoutez l'import QPushButton et QMessageBox et insérez le code suivant avant fenetre.show() :

from PySide6.QtWidgets import QPushButton, QMessageBox

# Création du bouton et de la fonction associée
def saluer():
prenom = saisie.text().strip() # Récupération et nettoyage du texte saisi
if prenom == "": # Si le champ est vide
# Message d'avertissement
QMessageBox.warning(fenetre, "Attention", "Veuillez entrer un prénom !")
# Sortie de la fonction
return
# Message de bienvenue personnalisé
QMessageBox.information(fenetre, "Bienvenue", f"Bonjour {prenom}, bienvenue dans PySide !")

bouton = QPushButton("Valider") # Création du bouton
bouton.clicked.connect(saluer) # Connexion du signal clicked à la fonction saluer

# Ajout du bouton au layout
layout.addWidget(bouton)

attention

En Python, la fonction saluer() peut accéder directement à la variable saisie sans qu’il soit nécessaire de la lui passer en paramètre, car saisie est définie dans la même portée globale que la fonction :

  • La variable saisie est créée dans le même bloc de code que la fonction saluer(), donc elle est visible et accessible à l’intérieur de cette fonction.
  • En Python, les fonctions peuvent accéder aux variables définies dans leur environnement extérieur (portée englobante), ce qui évite de devoir passer explicitement ces variables en argument.
  • Cela simplifie le code et évite de devoir modifier la signature de la fonction pour transmettre des widgets ou autres objets déjà accessibles.

Ainsi, dans ce cas, saluer() utilise directement saisie.text() pour récupérer le texte saisi, sans que saisie ait besoin d’être un paramètre de la fonction.

C’est une pratique courante en programmation Python avec des interfaces graphiques, où les widgets sont souvent créés dans un même scope et utilisés dans des fonctions de rappel (callbacks) sans passage explicite d’arguments.

remarque

La fonction saluer() récupère le texte via .text(), vérifie s’il est vide, puis utilise QMessageBox pour la boîte de dialogue.

9. Tester le programme complet en lançant python main.py :

Saisir un prénom et cliquer sur "Valider" doit afficher une boîte de dialogue native du système avec le message de bienvenue.

Corrigé

Une solution possible