Participer au site avec un Tip
Rechercher
 

Améliorations / Corrections

Vous avez des améliorations (ou des corrections) à proposer pour ce document : je vous remerçie par avance de m'en faire part, cela m'aide à améliorer le site.

Emplacement :

Description des améliorations :

Ajouter des widgets à la fenêtre

Votre première fenêtre graphique Liens avec les technologies Web


Accès rapide :
La vidéo
Topographie d'une fenêtre Qt
Définir la zone centrale
Ajouts de widgets dans la zone centrale
Réagir aux interactions de l'utilisateur sur les widgets

La vidéo

Cette fois-ci nous allons voir comment ajouter divers widgets à votre fenêtre graphique Qt.


Ajouter des widgets à la fenêtre.

Topographie d'une fenêtre Qt

Outre le bandeau de la fenêtre, qui est géré par le Window Manager de votre système d'exploitation, une fenêtre Qt est divisée en plusieurs parties distinctes. Au plus haut, on retrouve normalement l'espace associé à la barre de menu. En dessous se trouve la barre d'outils (il peut y en avoir plusieurs). Ensuite on trouve la zone centrale : c'est elle qui contiendra les principaux widgets de votre application. Enfin, vous trouverez en bas de la fenêtre une barre de statuts. Ces quatre zones sont directement gérées par la classe QMainWindow.

Topographie d'une fenêtre Qt

Pour les trois barres (menu, toolbar et statuts), si vous ne les demandez pas à la fenêtre, elles n'existeront pas et n'occuperont donc pas de place. Dans un telle cas, la zone centrale occupera tout l'espace de la fenêtre.

Définir la zone centrale

Pour le moment, nous allons ignorer les différentes barres (nous y reviendrons dans de prochains chapitres) et nous allons chercher à placer quelques widgets (quelques composants graphiques) dans la zone centrale et, pour ce faire, nous allons commencer par la définir. Dans l'exemple de code suivant, un widget de type QWidget est injecté dans la fenêtre en tant que widget central : c'est la méthode setCentralWidget qui réalise l'injection. Une couleur d'arrière-plan est définie pour ce widget afin de valider qu'il occupe bien tout l'espace disponible.

 1 
 2 
 3 
 4 
 5 
 6 
 7 
 8 
 9 
 10 
 11 
 12 
 13 
 14 
 15 
 16 
 17 
 18 
 19 
 20 
 21 
 22 
 23 
 24 
 25 
 26 
 27 
 28 
import sys

from PySide6.QtGui import QIcon
from PySide6.QtWidgets import QApplication, QMainWindow, QWidget


class MyWindow(QMainWindow):

    def __init__(self):
        super().__init__()
        self.setWindowTitle("Central area")
        self.setWindowIcon(QIcon("icons/file.png"))
        self.resize(600, 300)

        # Le type QWidget représente un conteneur de widgets (et il est lui-même un widget).
        # On crée une instance que l'on va mettre au centre de la fenêtre.
        centralArea = QWidget()
        # On lui met une couleur d'arrière-plan, histoire de bien le voir.
        centralArea.setStyleSheet("background: #419eee")
        # On injecte ce widget en tant que zone centrale.
        self.setCentralWidget(centralArea)


if __name__ == "__main__":
    app = QApplication(sys.argv)
    myWindow = MyWindow()
    myWindow.show()
    sys.exit(app.exec())
On injecte un widget dans la zone centrale

Et voici le résultat produit par l'exemple ci-dessus.

Injection d'un QWidget en tant que widget central.

Ajouts de widgets dans la zone centrale

La librairie Qt vous propose un large choix de widgets (de composants graphiques). Vouloir tous les énumérer pourrait s'avérer long et fastidieux tellement la librairie est riche. Pour autant, le tableau ci-dessous présente quelques classes de widgets : elles seront utilisées dans la démonstration qui va suivre.

Nom de la classe Description
QCalendarWidget Un widget permettant de sélectionner une date sur un calendrier.
QCheckBox Une case à cocher.
QLabel Un label permettant d'afficher un message
QLCDNumber Un label ayant un visuel d'un écran à cristaux liquides.
QLineEdit Un champ de saisie de texte sur une seule ligne.
QProgressBar Une barre de progression permettant d'informer de l'avancement d'une tâche.
QPushButton Un bouton poussoir classique.
QSlider Une réglette permettant de choisir une valeur dans un intervalle donné.
QSpinBox Un composant de saisie de valeurs entières.

Pour qu'un widget apparaisse dans la zone centrale plusieurs techniques peuvent être utilisées. La plus judicieuse serait d'utiliser un ou plusieurs layouts (des stratégies de positionnement de widgets) : nous parlerons de ces possibilités ultérieurement. Pour l'heure, je vais utiliser la technique la plus basique. Elle consiste à positionner un widget au pixel prêt, dans le conteneur.

Vous pouvez associer un widget à un conteneur en utilisant le constructeur du widget. En règle générale, le dernier paramètre d'un constructeur de widget correspond à son conteneur (on peut aussi dire son parent, mais sans connotation liée à l'heritage). Une fois le lien établi, il est possible de positionner et de dimensionner le widget en utilisant la méthode setGeometry.

 1 
 2 
 3 
 4 
# On place un calendrier dans la zone centrale.
calendar = QCalendarWidget(centralArea)
# On place le widget en (10, 10) et on le dimensionne avec 300 pixels de large et 200 pixels de haut.
calendar.setGeometry(10, 10, 300, 200)
Association et positionnement d'un widget dans son conteneur.
il existe différentes manières d'invoquer la méthode setGeometry. Je propose dans cet exemple d'invoquer la méthode avec quatre paramètres (la position en x, la position en y, la largeur et la hauteur du widget).

Voici un exemple de code injectant un widget de chacun des types proposés ci-dessus.

 1 
 2 
 3 
 4 
 5 
 6 
 7 
 8 
 9 
 10 
 11 
 12 
 13 
 14 
 15 
 16 
 17 
 18 
 19 
 20 
 21 
 22 
 23 
 24 
 25 
 26 
 27 
 28 
 29 
 30 
 31 
 32 
 33 
 34 
 35 
 36 
 37 
 38 
 39 
 40 
 41 
 42 
 43 
 44 
 45 
 46 
 47 
 48 
 49 
 50 
 51 
 52 
 53 
 54 
 55 
 56 
 57 
 58 
 59 
 60 
import sys

from PySide6.QtGui import QIcon, Qt
from PySide6.QtWidgets import QApplication, QMainWindow, QWidget, QCalendarWidget, QLabel, \
                              QPushButton, QCheckBox, QSpinBox, QLCDNumber, QLineEdit, \
                              QSlider, QProgressBar


class MyWindow(QMainWindow):

    def __init__(self):
        super().__init__()
        self.setWindowTitle("Some widgets")
        self.setWindowIcon(QIcon("icons/file.png"))
        self.resize(600, 300)

        # Le type QWidget représente un conteneur de widgets (et il est lui-même un widget).
        # On crée une instance que l'on va mettre au centre de la fenêtre.
        centralArea = QWidget()
        # On injecte ce widget en tant que zone centrale.
        self.setCentralWidget(centralArea)

        # On place maintenant chacun des composants souhaités dans la zone centrale.
        calendar = QCalendarWidget(centralArea)
        calendar.setGeometry(10, 10, 300, 200)

        lcd = QLCDNumber(self)
        lcd.display(1234)
        lcd.setGeometry(10, 220, 300, 70)

        label = QLabel("This is a label", centralArea)
        label.setGeometry(320, 10, 270, 30)

        button = QPushButton("This is a button", centralArea)
        button.setGeometry(320, 50, 270, 30)

        textBox = QLineEdit("This is a text box", centralArea)
        textBox.setGeometry(320, 90, 270, 30)

        checkBox = QCheckBox("This is a check box", centralArea)
        checkBox.setGeometry(320, 130, 270, 30)

        spinBox = QSpinBox(centralArea)
        spinBox.setValue(50)
        spinBox.setGeometry(320, 170, 270, 30)

        slider = QSlider(Qt.Horizontal, centralArea)
        slider.setValue(50)
        slider.setGeometry(320, 220, 270, 30)

        progress = QProgressBar(centralArea)
        progress.setValue(50)
        progress.setGeometry(320, 260, 270, 30)


if __name__ == "__main__":
    app = QApplication(sys.argv)
    myWindow = MyWindow()
    myWindow.show()
    sys.exit(app.exec())
Ajouts de widgets dans la zone centrale

Et voici le résultat produit par cet exemple.

Ajout de quelques composants graphiques dans le widget central.

Réagir aux interactions de l'utilisateur sur les widgets

Qt propose les mécanismes de slots et de signaux pour vous permettre de réagir aux interactions de l'utilisateur sur les différents widgets. Précisons quelques points de terminologie.

Par exemple, si l'on cherche à réagir au clic sur le bouton de notre interface graphique, il nous faut connaître le signal associé. Il s'agit du signal clicked. Une fois le signal identifié, vous pourrez utiliser sa méthode connect pour réaliser la connexion à votre slot. Voici comment réaliser la connexion.

 1 
button.clicked.connect(self.buttonClicked)
Connexion du signal exposé par le bouton sur notre slot.

Et le slot devra être définit ainsi :

 1 
 2 
 3 
 4 
@Slot()      # Pensez à importer le décorateur : from PySide6.QtCore import Slot
def buttonClicked(self):
    btn = self.sender()
    print(f"Button <{btn.text()}> clicked")
Implémentation d'un slot.
la méthode sender permet de retrouver le widget ayant déclenché le signal.

A titre d'exemple, nous allons chercher à réagir à la sélection d'une date dans le calendrier, au clic sur le bouton et à un changement de valeur sur le slider. Voici une nouvelle version du programme ajoutant les slots et les connexions nécessaires.

 1 
 2 
 3 
 4 
 5 
 6 
 7 
 8 
 9 
 10 
 11 
 12 
 13 
 14 
 15 
 16 
 17 
 18 
 19 
 20 
 21 
 22 
 23 
 24 
 25 
 26 
 27 
 28 
 29 
 30 
 31 
 32 
 33 
 34 
 35 
 36 
 37 
 38 
 39 
 40 
 41 
 42 
 43 
 44 
 45 
 46 
 47 
 48 
 49 
 50 
 51 
 52 
 53 
 54 
 55 
 56 
 57 
 58 
 59 
 60 
 61 
 62 
 63 
 64 
 65 
 66 
 67 
 68 
 69 
 70 
 71 
 72 
 73 
 74 
 75 
 76 
 77 
 78 
 79 
 80 
 81 
import sys
from datetime import date

from PySide6.QtCore import Slot
from PySide6.QtGui import QIcon, Qt
from PySide6.QtWidgets import QApplication, QMainWindow, QWidget, QCalendarWidget, QLabel, \
                              QPushButton, QCheckBox, QSpinBox, QLCDNumber, QLineEdit, \
                              QSlider, QProgressBar


class MyWindow(QMainWindow):

    def __init__(self):
        QMainWindow.__init__(self)
        self.setWindowTitle("Some widgets")
        self.setWindowIcon(QIcon("icons/file.png"))
        self.resize(600, 300)

        # Le type QWidget représente un conteneur de widgets (et il est lui-même un widget).
        # On crée une instance que l'on va mettre au centre de la fenêtre.
        centralArea = QWidget()
        # On injecte ce widget en tant que zone centrale.
        self.setCentralWidget(centralArea)

        calendar = QCalendarWidget(centralArea)
        calendar.setGeometry(10, 10, 300, 200)
        # On connecte le signal selectionChanged exposé par le calendier au slot dateSelected.
        calendar.selectionChanged.connect(self.dateSelected)

        lcd = QLCDNumber(self)
        lcd.display(1234)
        lcd.setGeometry(10, 220, 300, 70)

        label = QLabel("This is a label", centralArea)
        label.setGeometry(320, 10, 270, 30)

        button = QPushButton("This is a button", centralArea)
        button.setGeometry(320, 50, 270, 30)
        # On connecte le signal clicked exposé par le bouton au slot dateSelected.
        button.clicked.connect(self.buttonClicked)

        textBox = QLineEdit("This is a text box", centralArea)
        textBox.setGeometry(320, 90, 270, 30)

        checkBox = QCheckBox("This is a check box", centralArea)
        checkBox.setGeometry(320, 130, 270, 30)

        spinBox = QSpinBox(centralArea)
        spinBox.setValue(50)
        spinBox.setGeometry(320, 170, 270, 30)

        slider = QSlider(Qt.Horizontal, centralArea)
        slider.setValue(50)
        slider.setGeometry(320, 220, 270, 30)
        # On connecte le signal valueChanged exposé par le slider au slot valueChanged.
        slider.valueChanged.connect(self.valueChanged)

        progress = QProgressBar(centralArea)
        progress.setValue(50)
        progress.setGeometry(320, 260, 270, 30)

    @Slot()
    def dateSelected(self):
        calendar: QCalendarWidget = self.sender()
        print(f"Selected date is {calendar.selectedDate()}")

    @Slot()
    def buttonClicked(self):
        btn = self.sender()
        print(f"Button <{btn.text()}> clicked")

    @Slot(int)
    def valueChanged(self, value: int):
        print(f"Slider selected value is {value}")


if __name__ == "__main__":
    app = QApplication(sys.argv)
    myWindow = MyWindow()
    myWindow.show()
    sys.exit(app.exec())
Quelques connexions slots/signaux pour la gestion des événements.


Votre première fenêtre graphique Liens avec les technologies Web