"My Graph Generation Application" von Python (PySide + PyQtGraph) Teil 2

Teil 2-GUI-Programmierung mit PySide

So erstellen Sie eine GUI für PySide

Es gibt zwei Möglichkeiten, eine PySide-GUI zu erstellen. "(1) Wie man direkt trifft" und "(2) Wie man Qt Designer benutzt". Ersteres wird direkt in den Programmcode geschrieben und letzteres verwendet Werkzeuge. Persönlich denke ich, dass ① Ihnen helfen wird, PySide beim Erstellen einer GUI zu verstehen, daher werde ich diese dieses Mal verwenden.

Grob gesagt erstellt PySide eine GUI, indem Layouts und Widgets (GUI-Teile) wie unten gezeigt verschachtelt werden. Die Hauptlayouts sind diejenigen, die die Elemente horizontal wie das Enkelkind-Layout anordnen, diejenigen, die die Elemente vertikal wie das untergeordnete Layout anordnen, und diejenigen, die die Elemente im Raster (Raster) anordnen.

┏ Fenster ━━━━━━━━━━━━━━━━━━━┓
┃                        ┃
┃┏ Übergeordnetes Layout ━━━━━━━━━━━━━━━━┓┃
┃┃┏ untergeordnetes Layout ━━━━━━━━━━━┓┏━┓┃┃
┃┃┃┏ Son Layout ━━━━━━━━━┓┃┃┃┃┃
┃┃┃┃┏━━━━━━┳━━━━━━┓┃┃┃U┃┃┃
IdWidget ┃Widget ┃┃┃┃i┃┃┃
┃┃┃┃┗━━━━━━┻━━━━━━┛┃┃┃ji┃┃┃
┃┃┃┗━━━━━━━━━━━━━━━┛┃┃e┃┃┃
┃┃┃┏━━━━━━━━━━━━━━━┓┃┃ ┃┃┃
Get ┃ ┃ ┃ Widget ┃ ┃ ┃ To ┃ ┃ ┃
┃┃┃┗━━━━━━━━━━━━━━━┛┃┃ ┃┃┃
┃┃┗━━━━━━━━━━━━━━━━━┛┗━┛┃┃
┃┗━━━━━━━━━━━━━━━━━━━━━━┛┃
┗━━━━━━━━━━━━━━━━━━━━━━━━┛

Bei der Erstellung der GUI werden wir dieses Mal horizontales Layout, vertikales Layout und ein kleines spezielles Layout verwenden. Während der Arbeit mit PyQtGraph wird auch das Rasterlayout (wie) verwendet.

Wenn Sie die GUI tatsächlich in das Programm schreiben, ist es einfach, sie aus dem Inhalt zu erstellen. Mit anderen Worten

  1. Widget-Generierung und -Initialisierung
  2. Layouterstellung
  3. Speichern Sie das Widget-Layout in der Reihenfolge von innen im oberen Layout
  4. Legen Sie das übergeordnete Layout als Hauptlayout des Fensters fest

Ich werde den Code schreiben, der den Fluss hat.

GUI-Programmierung mit PySide

Lassen Sie uns sofort eine GUI erstellen. Im Folgenden werde ich den Code in der Reihenfolge von oben erläutern. Bitte fügen Sie in der Reihenfolge im vorherigen [4] \ _ \ _ init \ _ \ _ () hinzu. Der vollständige Text der Funktion wird am Ende aufgelistet.

# [4]
    #Initialisierung der MainWindow-Klasse(GUI-Generierung, Signalsteckplatzverbindung)
    def __init__(self, parent = None):
        super(MainWindow, self).__init__(parent)
        # [4-1]Legen Sie den Titel des Fensters fest
        self.setWindowTitle('Ich Graph Generierungsanwendung')
        

In der GUI-Programmierung ist die Entscheidung über einen Anwendungsnamen ein sehr heiliges Ritual. Sie können Ihre Anwendung mit der Funktion setWindowTitle () wie ** [4-1] ** zum Leben erwecken. Zu diesem Zeitpunkt ist der Inhalt noch leer, aber in der Titelleiste und der Taskleiste wird jetzt der von Ihnen genannte Name angezeigt. Fühlt es sich nicht etwas weniger lecker an? ……Ist das so.

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

Übrigens ist es auch möglich, das Symbol mit der Funktion self.setWindowIcon () festzulegen. Die Vorbereitung ist jedoch schwierig, daher werde ich sie hier weglassen.


        # [4-2]Stellen Sie den Koeffizienten ein
        self.keisu1 = 5.
        self.keisu2 = 10.
        
        # [4-3]Erstellen Sie GUI-Teile
        self.keisu1Label = QLabel('Faktor 1')
        self.keisu1Edit = QLineEdit(str(self.keisu1))
        self.keisu2Label = QLabel('Faktor 2')
        self.keisu2Edit = QLineEdit(str(self.keisu2))
        self.folderPathLabel = QLabel("Ordnerpfad:")
        self.folderPathEdit = QLineEdit(".\\")
        self.fileNameListWidget = QListWidget()
        self.button = QPushButton('Bildausgabe')
        
        # [4-4]GUI-Teile einstellen
        self.fileNameListWidget.setSelectionMode(QAbstractItemView.ExtendedSelection)
        

Bereiten Sie als Nächstes zwei Float-Koeffizienten vor, die beim Formatieren der Daten mit ** [4-2] ** verwendet werden sollen. ** [4-3] ** generiert die für diese Anwendung erforderlichen GUI-Teile: QLabel (Beschriftung), QLineEdit (einzeiliges Textfeld), QListWidget (Listen-Widget) und QPushButton (Schaltfläche). QLabel, QLineEdit und QPushButton können die Zeichenfolge im Widget gleichzeitig mit der Generierung anzeigen, indem sie eine Zeichenfolge in das Argument einfügt. folderPathEdit wird als Textfeld generiert, um in das Verzeichnis zu gelangen und die Dateiliste später anzuzeigen. Geben Sie vorerst den Ordner an, in dem sich diese Programmdatei (graphApp.py) mit einem relativen Pfad befindet. Wenn der Ordner mit der Datendatei des Versuchsergebnisses festgelegt ist, kann er leicht angegeben werden. Wenn Sie eine Einstellungsdatei erstellen, können Sie das zuletzt geöffnete Verzeichnis übernehmen. In ** [4-4] ** wurde das QListWidget-DateinameListWidget neu konfiguriert, sodass mehrere Inhalte ausgewählt werden können. In PySide-Referenz finden Sie verschiedene Einstellungselemente und Funktionen für jede GUI-Komponente. Auch wenn ich das Programm starte, wenn der GUI-Teil generiert wird, bleibt der Inhalt des Fensters leer. Dies liegt daran, dass das Layout noch nicht generiert und festgelegt wurde.


        # [4-5]Erstellen Sie einen Diagrammzeichnungsbereich für PyQtGraph
        self.lw = pg.LayoutWidget()
        self.lw.setMinimumSize(800, 600)
        self.lw.setMaximumSize(800, 600)
        

Das Layout-Widget, bei dem es sich um ein PyQtGraph-Widget handelt, wird in ** [4-5] ** generiert. Wie bereits erwähnt, ist PyQtGraph eine GUI-Bibliothek, die sich auf von PySide (Qt) abgeleitete Grafikzeichnungen spezialisiert hat. LayoutWidget ist eigentlich ein Widget, dessen Vererbungsquelle QWidget ist, sodass es im Layout von PySide installiert werden kann. Details werden nacheinander erklärt. Da ich gerade weitere Widgets hinzugefügt habe, ändert sich das Fenster auch dann nicht, wenn ich es wie gewohnt starte. Als nächstes erstellen wir das Layout.


        # [4-6]Erstellen Sie ein Layout und fügen Sie ein Widget hinzu
        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)
        

Für diese Anwendung werden drei Layouts verwendet: QFormLayout, QVBoxLayout und QHBoxLayout, wie in ** [4-6] ** gezeigt. QFormLayout ist ein Layout, mit dem Sie auf einfache Weise links eine Beschriftung und rechts ein Textfeld oder ein Optionsfeld erstellen können, die auf Formularbildschirmen üblich sind. Verwenden Sie die Funktion addRow (), um Beschriftungen und verschiedene Widgets als Satz im Layout hinzuzufügen. Andererseits sind QVBoxLayout und QHBoxLayout Layouts, in denen Elemente vertikal (vertikal) und horizontal (horizontal) angeordnet werden können. Durch Verwendung der Funktion addLayout () zusätzlich zur Funktion addWidget () können Sie eine komplexere GUI mit einer verschachtelten Struktur erstellen. Wenn Sie das Programm hier starten ... ändert sich nichts wie gewohnt. Schließlich müssen Sie "das übergeordnete Layout (Layout) auf das Hauptlayout des Fensters einstellen".


        # [4-7]Stellen Sie das Fensterlayout ein
        self.setLayout(layout)
        

Die Funktion setLayout () von ** [4-7] ** setzt das Layout auf das Hauptlayout der Fenster dieser Anwendung. Jetzt können Sie endlich die GUI unten im Fenster anzeigen.

その2成果

Wie wär es damit. Damit ist die Grundform der in dieser Zusammenfassung zu entwickelnden Graphgenerierungsanwendung vervollständigt.

  1. Widget-Generierung und -Initialisierung
  2. Layouterstellung
  3. Speichern Sie das Widget-Layout in der Reihenfolge von innen im oberen Layout
  4. Legen Sie das übergeordnete Layout als Hauptlayout des Fensters fest

Ich denke, es war überraschend einfach, eine Anwendung mit einer solchen GUI zu erstellen, indem ich die Schritte befolgte. In jedem Layout werden die Elemente in der Reihenfolge des Hinzufügens von oben (von links) ausgerichtet. Finden Sie Ihre eigene "I" -GUI, indem Sie die Reihenfolge ändern und andere GUI-Teile hinzufügen.

Und obwohl die GUI fertiggestellt wurde, wird sie noch ein wenig fortgesetzt.


        # [4-8]Verbinden Sie Signale und Steckplätze
        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]Aktualisieren Sie fileNameListWidget
        self.updateFileNameListWidget(self.fileNameListWidget, self.folderPathEdit.text())

Ich werde im nächsten Abschnitt über Signalschlitze sprechen, also werde ich die Geschichte von ** [4-8] ** vorerst verlassen. Verwenden Sie abschließend die Funktion ** [4-9] ** updateFileNameListWidget () für die ansonsten leere DateiNameListWidget, um die Dateiliste im angegebenen Ordner anzuzeigen, sobald sie gestartet wird. Da der Verarbeitungsteil der Funktion updateFileNameListWidget () jedoch nicht implementiert ist, wird er derzeit nur gleichzeitig mit dem Start an updateFileNameListWidget und die Eingabeaufforderung (Terminal / Terminal) ausgegeben.

Signale und Slots

Die Initialisierungsfunktion [4] \ _ \ _ init \ _ \ _ () in PySide spielt eine wichtige Rolle beim Erstellen der GUI und beim Verbinden von ** [4-8] ** Signalen und Slots.

Im Gegensatz zum prozeduralen CUI-Programm, das nur eine Verarbeitung wie "Wenn Sie den Namen, die Größe und das Gewicht eingeben, wird der BMI in der Reihenfolge von oben ausgegeben" erfordert, wird die GUI-Anwendung jederzeit und in beliebiger Reihenfolge ausgeführt. Es ist erforderlich, die Verarbeitung entsprechend der Schaltfläche oder dem Textfeld durchzuführen. Um diese sogenannte ereignisgesteuerte Programmierung durchzuführen, stellt PySide (Qt) den oben erwähnten Signal- und Schlitzmechanismus bereit.

Ich werde zu ** [4-8] ** zurückkehren und entsprechend erklären.

        # [4-8]Verbinden Sie Signale und Steckplätze
        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()))
        

Der obige Code verwendet den Signalschlitzmechanismus, um die folgenden zwei Operationen zu erreichen.

  1. Das Textfeld wird bearbeitet → Aktualisieren Sie die Dateiliste des Listen-Widgets
  2. Elemente im Listen-Widget sind ausgewählt → Zeichnen Sie ein Diagramm

"Signalschlitzverbindung", "über Code" bzw. "Anweisung 1" der beiden Codezeilen

Wird unterstützt. Die Bedeutung des Codes besteht darin, dass das Signal, dass das Textfeld bearbeitet wurde (textEdited) und die Funktion, die das Listen-Widget aktualisiert (updateFileNameListWidget ()), als Slots verwendet werden und die beiden verbunden sind (connect () -Funktion).

Ist der Signalsteckplatz beispielsweise eine Fernbedienung und ein Fernseher? Es wird gesagt, dass das eindeutige Mustersignal, das von der Fernbedienung übertragen wird, wenn die Taste gedrückt wird, und die entsprechenden TV-Funktionen (Kanalwechsel, Lautstärkeerhöhung usw.) im Voraus verknüpft werden.

Um zu überprüfen, ob die Signalsteckplatzverbindung tatsächlich hergestellt wurde, starten Sie diese Anwendung und bearbeiten Sie den Inhalt von folderPathEdit auf der GUI. Wahrscheinlich sollte es bei jeder Eingabe oder Löschung in "updateFileNameListWidget" und an die Eingabeaufforderung (Terminal / Terminal) ausgegeben werden.

Darüber hinaus werden für jedes Widget verschiedene Signale vorbereitet, z. B. das Klicken auf eine Schaltfläche (QButton.clicked) und der ausgewählte Satz (QPlainTextEdit.selectionChanged). Sie können auch eigene Signale erstellen. Ich werde. Darüber hinaus bedeutet "Lambda:", dass Sie einen Lambda-Ausdruck verwenden. Wenn Sie sich jedoch vorerst daran erinnern, werden Sie sehr glücklich sein (mit einem Lambda-Ausdruck können Sie Slot-Funktionen nach Belieben Argumente geben. Wird sein).

Vorschau beim nächsten Mal

Das ist alles über die GUI-Programmierung mit PySide. Das nächste Mal werden wir eine Funktion implementieren, die eine Dateiliste im Listen-Widget auf der GUI anzeigt, die die Verarbeitungseinheit diesmal nicht implementiert hat, und sogar die Datei lesen und die Daten generieren, die für das Zeichnen von Grafiken verwendet werden. Um ehrlich zu sein, denke ich, dass es je nach Person notwendig sein kann, dies zu erklären. In einem solchen Fall können Sie es überspringen.

Teil 1 - Einführung und Gesamtprogramm

Informationen zur GUI-Erstellung mit QtDesigner

Abschließend werde ich kurz die in "PySide GUI-Erstellungsmethode" erwähnte GUI-Erstellungsmethode "② Verwendung von Qt Designer" erläutern. QtDesigner ist ein Qt-Tool, mit dem Sie eine GUI auf der GUI erstellen können, die bei der Installation von PySide heruntergeladen wird. Es sollte sich in "(Python-Installationsziel) \ Lib \ site-packages \ PySide" mit einem Namen wie "designer.exe" befinden. Starten Sie es also und berühren Sie es. Zusätzlich zu den GUI-Teilen, die dieses Mal zum Erstellen der Diagrammgenerierungsanwendung verwendet werden, können Sie feststellen, dass eine Vielzahl von GUI-Teilen verfügbar ist. Mit QtDesigner können Sie Layouts und Widgets nach D & D anordnen, sodass das Erstellen einer grafischen Benutzeroberfläche Spaß macht. Tatsächlich wird die von QtDesigner generierte .ui-Datei von QtUiTools.QUiLoader im Programm selbst gelesen und verwendet.

[4] \ _ \ _ init \ _ \ _ () Funktion Volltext

# [4]
    #Initialisierung der MainWindow-Klasse(GUI-Generierung, Signalsteckplatzverbindung)
    def __init__(self, parent = None):
        super(MainWindow, self).__init__(parent)
        # [4-1]Legen Sie den Titel des Fensters fest
        self.setWindowTitle('Ich Graph Generierungsanwendung')
        
        # [4-2]Stellen Sie den Koeffizienten ein
        self.keisu1 = 5.
        self.keisu2 = 10.
        
        # [4-3]Erstellen Sie GUI-Teile
        self.keisu1Label = QLabel('Faktor 1')
        self.keisu1Edit = QLineEdit(str(self.keisu1))
        self.keisu2Label = QLabel('Faktor 2')
        self.keisu2Edit = QLineEdit(str(self.keisu2))
        self.folderPathLabel = QLabel("Ordnerpfad:")
        self.folderPathEdit = QLineEdit(".\\")
        self.fileNameListWidget = QListWidget()
        self.button = QPushButton('Bildausgabe')
        
        # [4-4]GUI-Teile einstellen
        self.fileNameListWidget.setSelectionMode(QAbstractItemView.ExtendedSelection)
        
        # [4-5]Erstellen Sie einen Diagrammzeichnungsbereich für PyQtGraph
        self.lw = pg.LayoutWidget()
        self.lw.setMinimumSize(800, 600)
        self.lw.setMaximumSize(800, 600)
        
        # [4-6]Erstellen Sie ein Layout und fügen Sie ein Widget hinzu
        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]Stellen Sie das Fensterlayout ein
        self.setLayout(layout)
        
        # [4-8]Verbinden Sie Signale und Steckplätze
        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]Aktualisieren Sie fileNameListWidget
        self.updateFileNameListWidget(self.fileNameListWidget, self.folderPathEdit.text())


Recommended Posts

"My Graph Generation Application" von Python (PySide + PyQtGraph) Teil 2
"My Graph Generation Application" von Python (PySide + PyQtGraph) Teil 1
Mein PySide (Python)
Python-Anwendung: Pandas Teil 1: Basic
Python-Anwendung: Pandas Teil 2: Serie
Python-Anwendung: Datenverarbeitung # 3: Datenformat
Primzahlgenerator von Python
Python-Anwendung: Numpy Teil 3: Double Array
Python-Anwendung: Datenvisualisierung Teil 1: Grundlegend
Anwendung von Python: Datenvisualisierung Teil 3: Verschiedene Grafiken
Anwendung von Python: Pandas Teil 4: Verketten und Kombinieren von DataFrames
Zeichnen Sie ein Diagramm mit PyQtGraph Part 1-Drawing
Zeichnen Sie ein Diagramm mit den PyQtGraph Part 3-PlotWidget-Einstellungen
Videorahmeninterpolation durch tiefes Lernen Teil 1 [Python]
Zeichnen Sie ein Diagramm mit den Einstellungen von PyQtGraph Part 4-PlotItem
Zeichnen Sie ein Diagramm mit PyQtGraph Teil 6 - Anzeigen einer Legende
Anwendung von Python: Datenverarbeitung Teil 2: Analyse verschiedener Datenformate