Développement d'Interfaces Graphiques avec PyQt6 : Premiers Pas et Méthodologies

PyQt6 est un ensemble de liaisons Python pour la boîte à outils multiplateforme Qt, développée par Riverbank Computing. Il permet aux développeurs Python de créer des applications graphiques robustes et performantes, compatibles avec les principaux systèmes d'exploitation tels qu'UNIX, Windows et macOS. Ce guide explore l'installation de PyQt6 et présente les approches fondamentales pour la conception d'interfaces utilisateur.

Installation de PyQt6

Avant d'installer PyQt6, assurez-vous de disposer d'un environnement Python fonctionnel. L'installation s'effectue facilement via pip, le gestionnaire de paquets de Python :

pip install pyqt6

Approches pour la Création d'Interfaces Utilisateur

Il existe deux méthodes principales pour construire des applications avec PyQt6 :

  1. Développement direct par code : Consiste à écrire manuellement tous les composants de l'interface et leur agencement dans le code Python.
  2. Utilisation de Qt Designer et conversion : Implique la conception visuelle de l'interface avec Qt Designer, puis la conversion du fichier .ui généré en code Python à l'aide de pyuic6, avant d'y ajouter la logique métier. Cette seconde appproche est souvent préférée pour sa rapidité et sa flexibilité.

Exemple 1 : Calculateur de Cercle (Approche par Code)

Nous allons illustrer la première méthode en créant une application simple qui calcule la circonférence et la surface d'un cercle à partir de son rayon. L'interface sera entièrement définie en Python, utilisant des gestionnaires de mise en page pour un positionnement flexible des éléments.

import sys
import math
from PyQt6.QtWidgets import QApplication, QWidget, QLabel, QLineEdit, QPushButton, QVBoxLayout, QHBoxLayout, QFormLayout
from PyQt6.QtCore import Qt

class CalculateurCercle(QWidget):
    def __init__(self):
        super().__init__()
        self.initialiserInterface()

    def initialiserInterface(self):
        self.setWindowTitle("Calculateur de Cercle")
        self.setMinimumSize(300, 200)

        # Création des widgets
        self.label_rayon = QLabel("Rayon:")
        self.champ_rayon = QLineEdit()
        self.champ_rayon.setPlaceholderText("Entrez le rayon ici")

        self.label_circonference = QLabel("Circonférence:")
        self.champ_circonference = QLineEdit()
        self.champ_circonference.setReadOnly(True)
        self.champ_circonference.setStyleSheet("background-color: #e0e0e0;")

        self.label_surface = QLabel("Surface:")
        self.champ_surface = QLineEdit()
        self.champ_surface.setReadOnly(True)
        self.champ_surface.setStyleSheet("background-color: #e0e0e0;")

        self.bouton_calculer = QPushButton("Calculer")
        self.bouton_calculer.clicked.connect(self.effectuerCalcul)

        # Configuration des mises en page (layouts)
        layout_form = QFormLayout()
        layout_form.addRow(self.label_rayon, self.champ_rayon)
        layout_form.addRow(self.label_circonference, self.champ_circonference)
        layout_form.addRow(self.label_surface, self.champ_surface)

        layout_bouton = QHBoxLayout()
        layout_bouton.addStretch(1) # Pousse le bouton vers le centre/droite
        layout_bouton.addWidget(self.bouton_calculer)
        layout_bouton.addStretch(1)

        layout_principal = QVBoxLayout()
        layout_principal.addLayout(layout_form)
        layout_principal.addStretch(1) # Pousse le formulaire vers le haut
        layout_principal.addLayout(layout_bouton)

        self.setLayout(layout_principal)

    def effectuerCalcul(self):
        """Calcule la circonférence et la surface du cercle."""
        try:
            rayon_texte = self.champ_rayon.text()
            rayon = float(rayon_texte)

            if rayon <= 0:
                self.champ_circonference.setText("Rayon > 0 requis")
                self.champ_surface.setText("Rayon > 0 requis")
                return

            circonference = round(2 * math.pi * rayon, 2)
            surface = round(math.pi * (rayon ** 2), 2)

            self.champ_circonference.setText(str(circonference))
            self.champ_surface.setText(str(surface))
        except ValueError:
            self.champ_circonference.setText("Saisie invalide")
            self.champ_surface.setText("Saisie invalide")

if __name__ == "__main__":
    app = QApplication(sys.argv)
    fenetre = CalculateurCercle()
    fenetre.show()
    sys.exit(app.exec())

Utilisation des Outils PyQt6 (Qt Designer)

Pour la méthode de conception visuelle, nous avons besoin des outils PyQt6. Installez-les :

pip install pyqt6-tools

Ce paquet inclut deux outils essentiels :

  • Qt Desinger : Un éditeur d'interface graphique WYSIWYG (What You See Is What You Get) pour créer des interfaces par glisser-déposer. Le fichier exécutable designer.exe se trouve généralement dans le répertoire d'installation de Python (par exemple, python\Lib\site-packages\qt6_applications\Qt\bin\designer.exe).
  • pyuic6 : Un utilitaire de ligne de commande pour convertir les fichiers d'interface .ui générés par Qt Designer en modules Python.

Conversion d'un fichier .ui en .py

Après avoir conçu votre interface avec Qt Designer et l'avoir sauvegardée sous un nom comme calculateur_cercle.ui, utilisez pyuic6 pour la convertir :

pyuic6 -o ui_calculateur_cercle.py calculateur_cercle.ui

Ceci générera un fichier Python (par exemple, ui_calculateur_cercle.py) contenant une classe (souvent nommée Ui_MainWindow ou Ui_Form) avec la structure de votre interface.

Exemple 2 : Calculateur de Cercle (Approche Qt Designer)

Dans cette approche, nous supposons que vous avez créé une interface similaire à l'exemple précédent via Qt Designre, avec des champs de texte nommés lineEdit_rayon, lineEdit_circonference, lineEdit_surface, et un bouton nommé pushButton_calculer. Le fichier ui_calculateur_cercle.py est généré comme décrit ci-dessus.

Voici comment intégrer ce fichier dans votre application Python principale :

import sys
import math
from PyQt6.QtWidgets import QApplication, QWidget
from PyQt6.uic import loadUi # Alternative: from ui_calculateur_cercle import Ui_Form

class MaFenetreCalculateur(QWidget):
    def __init__(self, ui_file_path="calculateur_cercle.ui"):
        super().__init__()
        # Charger l'interface depuis le fichier .ui directement
        # Alternative plus robuste: hériter de la classe générée par pyuic6
        # from ui_calculateur_cercle import Ui_Form
        # Ui_Form.__init__(self) # ou super().__init__() si on hérite directement
        # self.setupUi(self)
        loadUi(ui_file_path, self) # Charge l'UI dans cette instance de QWidget
        self.setWindowTitle("Calculateur de Cercle (Designer)")
        self.connecterSignaux()
        self.configurerChamps()

    def connecterSignaux(self):
        """Connecte les signaux des widgets aux slots correspondants."""
        self.pushButton_calculer.clicked.connect(self.effectuerCalcul)

    def configurerChamps(self):
        """Configure les propriétés des champs de texte en lecture seule."""
        self.lineEdit_circonference.setReadOnly(True)
        self.lineEdit_surface.setReadOnly(True)
        self.lineEdit_circonference.setStyleSheet("background-color: #e0e0e0;")
        self.lineEdit_surface.setStyleSheet("background-color: #e0e0e0;")

    def effectuerCalcul(self):
        """Calcule la circonférence et la surface du cercle à partir des données de l'UI."""
        try:
            rayon_texte = self.lineEdit_rayon.text()
            rayon = float(rayon_texte)

            if rayon <= 0:
                self.lineEdit_circonference.setText("Rayon > 0 requis")
                self.lineEdit_surface.setText("Rayon > 0 requis")
                return

            circonference = round(2 * math.pi * rayon, 2)
            surface = round(math.pi * (rayon ** 2), 2)

            self.lineEdit_circonference.setText(str(circonference))
            self.lineEdit_surface.setText(str(surface))
        except ValueError:
            self.lineEdit_circonference.setText("Saisie invalide")
            self.lineEdit_surface.setText("Saisie invalide")

if __name__ == "__main__":
    app = QApplication(sys.argv)
    # Assurez-vous que 'calculateur_cercle.ui' existe dans le même répertoire ou spécifiez un chemin.
    fenetre_designer = MaFenetreCalculateur("calculateur_cercle.ui")
    fenetre_designer.show()
    sys.exit(app.exec())

Note : L'exemple ci-dessus utilise loadUi pour simplifier. Une pratique courante pour des projets plus complexes est d'hériter de la classe Ui_Form (ou Ui_MainWindow) générée par pyuic6 pour une meilleure séparation des préoccupations.

Packaging de l'Application avec PyInstaller

Une fois votre application PyQt6 développée, vous pouvez la distribuer sous forme d'exécutable autonome. PyInstaller est un outil populaire pour cette tâche :

pip install pyinstaller

Pour packager votre script principal (par exemple, app_principale.py) en un seul fichier exécutable :

pyinstaller --onefile app_principale.py

Ceci créera un dossier dist contenant votre application sous forme d'un exécutable.

Étiquettes: PyQt6 Python interface graphique Qt Designer pyuic6

Publié le 1 août à 21h10