"My Graph Generation Application" par Python (PySide + PyQtGraph) Partie 2

Partie 2-Programmation GUI avec PySide

Comment créer une interface graphique pour PySide

Il existe deux façons de créer une interface graphique PySide. "(1) Comment frapper directement" et "(2) Comment utiliser Qt Designer". Le premier est écrit directement dans le code du programme et le second utilise des outils. Personnellement, je pense que ① vous aidera à comprendre PySide lors de la création d'une interface graphique, je vais donc utiliser celle-ci cette fois.

En gros, PySide crée une interface graphique en imbriquant des dispositions et des widgets (parties de l'interface graphique) comme indiqué ci-dessous. Les mises en page principales sont celles qui organisent les éléments horizontalement comme la mise en page petit-enfant, celles qui organisent les éléments verticalement comme la mise en page enfant et celles qui organisent les éléments sur la grille (grille).

┏ Fenêtre ━━━━━━━━━━━━━━━━━━━┓
┃                        ┃
┃┏ Disposition parent
┃┃┏ mise en page enfant ━━━━━━━━━━━┓┏━┓┃┃
┃┃┃┏ Disposition des fils ━━━━━━━━━┓┃┃┃┃┃
┃┃┃┃┏━━━━━━┳━━━━━━┓┃┃┃U┃┃┃
┃┃┃┃┃Widget ┃Widget ┃┃┃┃i┃┃┃
┃┃┃┃┗━━━━━━┻━━━━━━┛┃┃┃ji┃┃┃
┃┃┃┗━━━━━━━━━━━━━━━┛┃┃e┃┃┃
┃┃┃┏━━━━━━━━━━━━━━━┓┃┃ ┃┃┃
┃ ┃ ┃ ┃ Widget ┃ ┃ ┃ Pour ┃ ┃ ┃
┃┃┃┗━━━━━━━━━━━━━━━┛┃┃ ┃┃┃
┃┃┗━━━━━━━━━━━━━━━━━┛┗━┛┃┃
┃┗━━━━━━━━━━━━━━━━━━━━━━┛┃
┗━━━━━━━━━━━━━━━━━━━━━━━━┛

En créant l'interface graphique cette fois, nous utiliserons une disposition horizontale, une disposition verticale et une petite disposition spéciale. De plus, la disposition de la grille (comme) sera utilisée lors de l'utilisation de PyQtGraph.

Lors de l'écriture de l'interface graphique dans le programme, il est basique de la créer à partir du contenu. En d'autres termes

  1. Génération et initialisation des widgets
  2. Génération de mise en page
  3. Stockez la disposition du widget dans la disposition supérieure dans l'ordre de l'intérieur
  4. Définissez la mise en page parent comme mise en page principale de la fenêtre

J'écrirai le code qui a le flux.

Programmation GUI avec PySide

Créons une interface graphique à la fois. Ci-dessous, je vais expliquer le code dans l'ordre du haut. Veuillez ajouter dans l'ordre dans le précédent [4] \ _ \ _ init \ _ \ _ (). Le texte intégral de la fonction est répertorié à la fin.

# [4]
    #Initialisation de la classe MainWindow(Génération d'interface graphique, connexion de fente de signal)
    def __init__(self, parent = None):
        super(MainWindow, self).__init__(parent)
        # [4-1]Définir le titre de la fenêtre
        self.setWindowTitle('Application de génération de graphes')
        

Dans la programmation GUI, la tâche de décider d'un nom d'application est un rituel très sacré. Vous pouvez donner vie à votre application en utilisant la fonction setWindowTitle () comme ** [4-1] **. Au démarrage à ce stade, le contenu est toujours vide, mais la barre de titre et la barre des tâches affichent désormais le nom que vous avez nommé. N'est-ce pas comme si c'était un peu moins savoureux? ……Est-ce vrai.

ウィンドウタイトルの表示

En passant, il est également possible de définir l'icône avec la fonction self.setWindowIcon (). Cependant, il est difficile à préparer, je vais donc l'omettre ici.


        # [4-2]Réglez le coefficient
        self.keisu1 = 5.
        self.keisu2 = 10.
        
        # [4-3]Créer des pièces GUI
        self.keisu1Label = QLabel('Facteur 1')
        self.keisu1Edit = QLineEdit(str(self.keisu1))
        self.keisu2Label = QLabel('Facteur 2')
        self.keisu2Edit = QLineEdit(str(self.keisu2))
        self.folderPathLabel = QLabel("Chemin du dossier:")
        self.folderPathEdit = QLineEdit(".\\")
        self.fileNameListWidget = QListWidget()
        self.button = QPushButton('Sortie d'image')
        
        # [4-4]Définir les pièces de l'interface graphique
        self.fileNameListWidget.setSelectionMode(QAbstractItemView.ExtendedSelection)
        

Ensuite, préparez deux coefficients de type flottant à utiliser lors du formatage des données avec ** [4-2] **. ** [4-3] ** génère les parties GUI requises pour cette application: QLabel (étiquette), QLineEdit (zone de texte sur une ligne), QListWidget (widget de liste) et QPushButton (bouton). QLabel, QLineEdit et QPushButton peuvent afficher la chaîne de caractères à l'intérieur du widget en même temps qu'elle est générée en mettant une chaîne de caractères dans l'argument. folderPathEdit est généré sous forme de zone de texte pour entrer dans le répertoire pour afficher la liste des fichiers ultérieurement. Pour le moment, spécifions le dossier où se trouve ce fichier programme (graphApp.py) avec un chemin relatif. Si le dossier contenant le fichier de données du résultat expérimental est choisi, il est facile de le spécifier, et si vous créez un fichier de paramètres, vous pouvez reprendre le répertoire qui a été ouvert la dernière fois. Dans ** [4-4] **, le QListWidget fileNameListWidget a été reconfiguré pour que plusieurs contenus puissent être sélectionnés. Veuillez vous référer à PySide Reference pour les différents éléments de réglage et fonctions de chaque composant GUI. Même si je lance le programme lorsque la partie GUI est générée, le contenu de la fenêtre reste vide. En effet, la mise en page n'a pas encore été générée et définie.


        # [4-5]Créer une zone de dessin graphique pour PyQtGraph
        self.lw = pg.LayoutWidget()
        self.lw.setMinimumSize(800, 600)
        self.lw.setMaximumSize(800, 600)
        

Le widget de mise en page, qui est un widget PyQtGraph, est généré en ** [4-5] **. Comme mentionné la dernière fois, PyQtGraph est une bibliothèque d'interface graphique spécialisée dans le dessin de graphe dérivé de PySide (Qt). LayoutWidget est en fait un widget dont la source d'héritage est QWidget, il peut donc être installé dans la mise en page de PySide. Les détails seront expliqués les uns après les autres. Depuis que je viens d'ajouter plus de widgets, la fenêtre ne change pas même si je la lance comme d'habitude. Ensuite, créons la mise en page.


        # [4-6]Créer une mise en page et ajouter un widget
        keisuLayout = QFormLayout()
        keisuLayout.addRow(self.keisu1Label, self.keisu1Edit)
        keisuLayout.addRow(self.keisu2Label, self.keisu2Edit)
        folderLayout = QFormLayout()
        folderLayout.addRow(self.folderPathLabel, self.folderPathEdit)
        
        leftLayout = QVBoxLayout()
        leftLayout.addLayout(keisuLayout)
        leftLayout.addLayout(folderLayout)
        leftLayout.addWidget(self.fileNameListWidget)
        leftLayout.addWidget(self.button)
        
        layout = QHBoxLayout()
        layout.addLayout(leftLayout)
        layout.addWidget(self.lw)
        

Trois mises en page sont utilisées pour cette application: QFormLayout, QVBoxLayout et QHBoxLayout comme indiqué dans ** [4-6] **. QFormLayout est une mise en page qui facilite la composition d'une étiquette à gauche et d'une zone de texte ou d'un bouton radio à droite, qui sont courantes sur les écrans de formulaire. Utilisez la fonction addRow () pour ajouter des étiquettes et divers widgets en tant qu'ensemble dans la mise en page. D'autre part, QVBoxLayout et QHBoxLayout sont des dispositions dans lesquelles les éléments peuvent être disposés verticalement (verticalement) et horizontalement (horizontalement). En utilisant la fonction addLayout () en plus de la fonction addWidget (), vous pouvez créer une interface graphique plus complexe avec une structure imbriquée. Si vous démarrez le programme ici ... rien ne changera comme d'habitude. Enfin, vous devez "définir la mise en page parent (mise en page) sur la mise en page principale de la fenêtre".


        # [4-7]Définir la disposition de la fenêtre
        self.setLayout(layout)
        

La fonction setLayout () de ** [4-7] ** définit la disposition sur la disposition principale des fenêtres de cette application. Maintenant, vous pouvez enfin afficher l'interface graphique ci-dessous dans la fenêtre.

その2成果

Et ça. Ceci complète la forme de base de l'application de génération de graphes à développer dans ce résumé.

  1. Génération et initialisation des widgets
  2. Génération de mise en page
  3. Stockez la disposition du widget dans la disposition supérieure dans l'ordre de l'intérieur
  4. Définissez la mise en page parent comme mise en page principale de la fenêtre

En suivant les étapes décrites, je pense qu'il était étonnamment facile de créer une application avec une interface graphique comme celle-là. Dans chaque mise en page, les éléments sont alignés à partir du haut (à partir de la gauche) dans l'ordre d'ajout. Veuillez trouver votre propre interface graphique "I" en modifiant l'ordre et en ajoutant d'autres parties de l'interface graphique.

Et, bien que l'interface graphique soit terminée, elle continuera un peu plus.


        # [4-8]Connectez les signaux et les slots
        self.folderPathEdit.textEdited.connect(lambda: self.updateFileNameListWidget(self.fileNameListWidget, self.folderPathEdit.text()))
        self.fileNameListWidget.itemSelectionChanged.connect(lambda: self.createGraph(self.folderPathEdit.text(), self.fileNameListWidget.selectedItems()[0].text()))
        
        # [4-9]Mettre à jour fileNameListWidget
        self.updateFileNameListWidget(self.fileNameListWidget, self.folderPathEdit.text())

Je parlerai des slots de signal dans la section suivante, donc je vais laisser l'histoire de ** [4-8] ** pour le moment. Enfin, utilisez la fonction ** [4-9] ** updateFileNameListWidget () sur le fileNameListWidget vide pour afficher la liste de fichiers dans le dossier spécifié dès son démarrage. Cependant, comme la partie traitement de la fonction updateFileNameListWidget () n'est pas implémentée, pour le moment elle n'est sortie que vers ʻupdateFileNameListWidget` et l'invite de commande (terminal / terminal) en même temps que le démarrage.

Signaux et slots

La fonction d'initialisation [4] \ _ \ _ init \ _ \ _ () dans PySide joue un rôle majeur dans la création de l'interface graphique et dans la connexion des signaux ** [4-8] ** et des slots.

Contrairement au programme CUI procédural, qui ne nécessite qu'un traitement tel que «lorsque vous entrez le nom, la taille et le poids, l'IMC est sorti» dans l'ordre du haut, l'application GUI fonctionne à tout moment et dans n'importe quel ordre. Il est nécessaire d'effectuer le traitement correspondant au bouton ou à la zone de texte. Afin d'effectuer cette soi-disant programmation événementielle, PySide (Qt) fournit le signal et le mécanisme de créneau mentionnés ci-dessus.

Je reviendrai à ** [4-8] ** et expliquerai en conséquence.

        # [4-8]Connectez les signaux et les slots
        self.folderPathEdit.textEdited.connect(lambda: self.updateFileNameListWidget(self.fileNameListWidget, self.folderPathEdit.text()))
        self.fileNameListWidget.itemSelectionChanged.connect(lambda: self.createGraph(self.folderPathEdit.text(), self.fileNameListWidget.selectedItems()[0].text()))
        

Le code ci-dessus utilise le mécanisme de créneau de signal pour réaliser les deux opérations suivantes.

  1. La zone de texte est modifiée → Mettre à jour la liste des fichiers du widget liste
  2. Les éléments du widget de liste sont sélectionnés → Dessiner un graphique

"Connexion de tranche de signal", "au-dessus du code" et "instruction 1" des deux lignes de code, respectivement

Est pris en charge. La signification du code est que le signal que la zone de texte a été modifiée (textEdited) et la fonction qui met à jour le widget de liste (updateFileNameListWidget ()) sont utilisés comme emplacements, et les deux sont connectés (fonction connect ()).

La connexion de la fente de signal est-elle, par exemple, une télécommande et un téléviseur? On dit que le signal de motif unique transmis par la télécommande lorsque le bouton est enfoncé et les fonctions TV correspondantes (changement de chaîne, augmentation de volume, etc.) sont liées à l'avance.

Pour vérifier si la connexion de la fente de signal est réellement établie, démarrez cette application et modifiez le contenu de folderPathEdit sur l'interface graphique. Il devrait probablement être affiché dans ʻupdateFileNameListWidget` et l'invite de commande (terminal / terminal) à chaque fois que vous le saisissez ou le supprimez.

En plus de cela, divers signaux sont préparés pour chaque widget, tels que le bouton cliqué (QButton.clicked) et le texte sélectionné (QPlainTextEdit.selectionChanged), et vous pouvez également créer le vôtre. Je vais. De plus, lambda: signifie que vous utilisez une expression lambda, mais si vous vous en souvenez pour le moment, vous serez très heureux (en utilisant une expression lambda, vous pouvez donner des arguments à la fonction slot comme vous le souhaitez. Sera).

Aperçu de la prochaine fois

Tout est question de programmation GUI avec PySide. La prochaine fois, nous allons implémenter une fonction qui affiche une liste de fichiers dans le widget de liste sur l'interface graphique que l'unité de traitement n'a pas implémentée cette fois, et même lire le fichier et générer les données utilisées pour le dessin graphique. Eh bien, pour être honnête, je pense qu'il peut être nécessaire d'expliquer en fonction de la personne, donc dans un tel cas, vous pouvez l'ignorer.

Partie 1-Introduction et programme général

À propos de la création d'interface graphique à l'aide de QtDesigner

Enfin, j'expliquerai brièvement la méthode de création de GUI "② Comment utiliser Qt Designer" mentionnée dans "PySide GUI creation method". QtDesigner est un outil Qt qui vous permet de créer une interface graphique sur l'interface graphique qui est téléchargée en même temps que PySide est installé. Il doit être dans "(destination de l'installation Python) \ Lib \ site-packages \ PySide" avec un nom tel que "designer.exe", alors démarrez-le et touchez-le. En plus des parties GUI utilisées pour créer l'application de génération de graphiques cette fois, vous pouvez voir qu'il existe une grande variété de parties GUI disponibles. QtDesigner vous permet d'organiser les mises en page et les widgets par D & D, il est donc amusant de créer facilement une interface graphique. En fait, le fichier .ui généré par QtDesigner est lu par QtUiTools.QUiLoader dans le programme lui-même et utilisé.

[4] \ _ \ _ init \ _ \ _ () fonction texte intégral

# [4]
    #Initialisation de la classe MainWindow(Génération d'interface graphique, connexion de fente de signal)
    def __init__(self, parent = None):
        super(MainWindow, self).__init__(parent)
        # [4-1]Définir le titre de la fenêtre
        self.setWindowTitle('Application de génération de graphes')
        
        # [4-2]Réglez le coefficient
        self.keisu1 = 5.
        self.keisu2 = 10.
        
        # [4-3]Créer des pièces GUI
        self.keisu1Label = QLabel('Facteur 1')
        self.keisu1Edit = QLineEdit(str(self.keisu1))
        self.keisu2Label = QLabel('Facteur 2')
        self.keisu2Edit = QLineEdit(str(self.keisu2))
        self.folderPathLabel = QLabel("Chemin du dossier:")
        self.folderPathEdit = QLineEdit(".\\")
        self.fileNameListWidget = QListWidget()
        self.button = QPushButton('Sortie d'image')
        
        # [4-4]Définir les pièces de l'interface graphique
        self.fileNameListWidget.setSelectionMode(QAbstractItemView.ExtendedSelection)
        
        # [4-5]Créer une zone de dessin graphique pour PyQtGraph
        self.lw = pg.LayoutWidget()
        self.lw.setMinimumSize(800, 600)
        self.lw.setMaximumSize(800, 600)
        
        # [4-6]Créer une mise en page et ajouter un widget
        keisuLayout = QFormLayout()
        keisuLayout.addRow(self.keisu1Label, self.keisu1Edit)
        keisuLayout.addRow(self.keisu2Label, self.keisu2Edit)
        folderLayout = QFormLayout()
        folderLayout.addRow(self.folderPathLabel, self.folderPathEdit)
        
        leftLayout = QVBoxLayout()
        leftLayout.addLayout(keisuLayout)
        leftLayout.addLayout(folderLayout)
        leftLayout.addWidget(self.fileNameListWidget)
        leftLayout.addWidget(self.button)
        
        layout = QHBoxLayout()
        layout.addLayout(leftLayout)
        layout.addWidget(self.lw)
        
        # [4-7]Définir la disposition de la fenêtre
        self.setLayout(layout)
        
        # [4-8]Connectez les signaux et les slots
        self.folderPathEdit.textEdited.connect(lambda: self.updateFileNameListWidget(self.fileNameListWidget, self.folderPathEdit.text()))
        self.fileNameListWidget.itemSelectionChanged.connect(lambda: self.createGraph(self.folderPathEdit.text(), self.fileNameListWidget.selectedItems()[0].text()))
        
        # [4-9]Mettre à jour fileNameListWidget
        self.updateFileNameListWidget(self.fileNameListWidget, self.folderPathEdit.text())


Recommended Posts

"My Graph Generation Application" par Python (PySide + PyQtGraph) Partie 2
"My Graph Generation Application" par Python (PySide + PyQtGraph) Partie 1
Mon PySide (Python)
Application Python: Pandas Partie 1: Basique
Application Python: Pandas Partie 2: Série
Application Python: Traitement des données # 3: Format des données
Générateur de nombres premiers par Python
Application Python: Numpy Partie 3: Double tableau
Application Python: visualisation de données partie 1: basique
Application de Python: visualisation de données Partie 3: divers graphiques
Application de Python: Pandas Partie 4: Concaténation et combinaison de DataFrames
Dessinez un graphique avec PyQtGraph Part 1-Drawing
Dessinez un graphique avec les paramètres PyQtGraph Partie 3-PlotWidget
Interpolation d'images vidéo par apprentissage en profondeur, partie 1 [Python]
Dessinez un graphique avec les paramètres PyQtGraph Part 4-PlotItem
Dessinez un graphique avec PyQtGraph Partie 6 - Affichage d'une légende
Application de Python: Traitement des données Partie 2: Analyse de divers formats de données