Présentation de l'interface graphique: PyQt5 en Python

Pourquoi Python est GUI?


Pourquoi Python au lieu de Ruby, JS, C #?

  1. Facile à écrire le langage Python lui-même (vs JS)
  2. Fonctionne sur Windows et Mac (vs Ruby, C #)
  3. Vaste bibliothèque pour l'analyse des données et le traitement d'images
  4. Le code C / C ++ peut être appelé avec ctypes et Cython

Les principales bibliothèques GUI de Python


Présentation de PyQt5


Qt est un framework d'application OSS

--1992 ~ (actuellement v5.8)


PyQt5 est un wrapper pour Qt5.x

Un outil appelé SIP est utilisé pour générer la partie C ++ <=> Python.


Exemple de PyQt5


Placer des widgets standard

Afficher la valeur actuelle de la barre de défilement sous forme de chaîne de caractères

from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
import sys

class Sample1(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent=parent)

        s = QScrollBar(orientation=Qt.Horizontal)
        t = QLabel()

        s.valueChanged.connect(lambda v: t.setText(str(v)))

        l = QVBoxLayout()
        l.addWidget(s)
        l.addWidget(t)
        self.setLayout(l)

app = QApplication(sys.argv)
s = Sample1()
s.show()
sys.exit(app.exec_())

Exemple 1


Disposition


signal

→ Empêcher les widgets de se coupler étroitement avec la couche de modèle → Plus flexible que la méthode de rappel


Connectez les signaux dans les deux sens

from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
import sys

class Sample2(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent=parent)

        l = QVBoxLayout()
        
        t = QLabel()
        s1 = QScrollBar(orientation=Qt.Horizontal)
        s1.valueChanged.connect(lambda v: t.setText(str(v)))

        s2 = QScrollBar(orientation=Qt.Horizontal)
        s3 = QSpinBox()
        s4 = QSpinBox()
        s5 = QSpinBox()

        s1.valueChanged.connect(s2.setValue)
        s2.valueChanged.connect(s3.setValue)
        s3.valueChanged.connect(s4.setValue)
        s4.valueChanged.connect(s5.setValue)
        s5.valueChanged.connect(s1.setValue)

        l.addWidget(s1)
        l.addWidget(s2)
        l.addWidget(s3)
        l.addWidget(s4)
        l.addWidget(s5)
        l.addWidget(t)

        self.setLayout(l)

app = QApplication(sys.argv)
s = Sample2()
s.show()
sys.exit(app.exec_())

Exemple 2


Katsura volant


#Données (carte actuelle)
class BoardState:

#modèle
class BoardModel(QObject):
    stateChanged = pyqtSignal(BoardState)
    def moveKnightTo(self, x, y):
    def rollback(self):

#Widget (une cellule à la fois)
class BoardCellWidget(QLabel):
    knightMoved = pyqtSignal(tuple)
    def setState(self, state):

#Un widget qui a un modèle et affiche 64 cellules
class BoardWidget(QWidget):

from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
import sys

class BoardState:
    def __init__(self, x, y):
        self._x = x
        self._y = y
        
    def knightIn(self, x, y):
        return (self._x, self._y) == (x, y)
    
    def canKnightMoveTo(self, x, y):
        dx = abs(self._x - x)
        dy = abs(self._y - y)
        return (dx, dy) in [(1, 2), (2, 1)]
        

class BoardModel(QObject):
    stateChanged = pyqtSignal(BoardState)

    def __init__(self, parent=None):
        super().__init__(parent=parent)
        self._states = [BoardState(0, 0)]

    def moveKnightTo(self, x, y):
        newState = BoardState(x, y)
        self._states.append(newState)
        self.stateChanged.emit(newState)

    def rollback(self):
        if len(self._states) <= 1:
            return
        self._states = self._states[:-1]
        self.stateChanged.emit(self._states[-1])

    def state(self):
        return self._states[-1]


class BoardCellWidget(QLabel):
    knightMoved = pyqtSignal(tuple)

    def __init__(self, parent, x, y):
        super().__init__(parent=parent)
        self._x = x
        self._y = y

        self.setMinimumSize(QSize(32, 32))
        self.setMouseTracking(True)
        self.setAcceptDrops(True)

    def setState(self, state):
        self._state = state
        self.update()

    def mousePressEvent(self, event):
        if event.button() == Qt.LeftButton:
            drag = QDrag(self)
            data = QMimeData()
            data.setText("knight")
            drag.setMimeData(data)
            drag.exec()

            event.accept()

    def dropEvent(self, event):
        if self._state.canKnightMoveTo(self._x, self._y):
            self.knightMoved.emit((self._x, self._y))
            event.acceptProposedAction()

    def dragEnterEvent(self, event):
        if self._state.canKnightMoveTo(self._x, self._y):
            event.acceptProposedAction()

    def paintEvent(self, event):
        p = QPainter(self)

        if (self._x + self._y) % 2 == 1:
            p.setBackground(QColor(0xD3, 0x8C, 0x40))
        else:
            p.setBackground(QColor(0xFF, 0xCF, 0x9B))
        p.eraseRect(self.rect())

        rect = QRect(4, 4, self.width() - 8, self.height() - 8)
        if self._state.knightIn(self._x, self._y):
            p.fillRect(rect, Qt.white)
        elif self._state.canKnightMoveTo(self._x, self._y):
            p.fillRect(rect, Qt.green)


class BoardWidget(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent=parent)

        self._model = BoardModel(parent=self)

        l = QGridLayout()
        for x in range(8):
            for y in range(8):
                cell = BoardCellWidget(parent, x, y)
                cell.setState(self._model.state())
                self._model.stateChanged.connect(cell.setState)
                cell.knightMoved.connect(lambda xy: self._model.moveKnightTo(*xy))
                l.addWidget(cell, x, y)

        l1 = QHBoxLayout()
        l1.addLayout(l, 1)
        self._rollback = QPushButton("rollback", parent=self)
        self._rollback.pressed.connect(self._model.rollback)
        l1.addWidget(self._rollback, 0)
        self.setLayout(l1)

app = QApplication(sys.argv)

b = BoardWidget()
b.show()
sys.exit(app.exec_())

Exemple 3


Supplément

--Il existe également un DSL appelé QML / QtQuick


Malheureusement


Q&A

** Q. ** Pourquoi une boucle infinie ne se produit-elle pas même si les widgets sont connectés dans une boucle avec ʻa.valueChanged.connect (b.setValue) ? ** A. ** valueChanged` n'est émis que" lorsque la valeur est modifiée ".

Recommended Posts

Présentation de l'interface graphique: PyQt5 en Python
[GUI en Python] PyQt5 -Event-
[GUI en Python] PyQt5-Dialog-
Présentation de Python en pratique (PiP)
[GUI avec Python] PyQt5-Préparation-
[GUI avec Python] PyQt5 -Paint-
Programmation GUI en Python avec Appjar
[GUI avec Python] PyQt5 -Widget II-
[GUI avec Python] PyQt5-Widget personnalisé-
[GUI en Python] Menu PyQt5 et barre d'outils-
Création d'interface graphique en python avec tkinter 2
Essayez de le faire avec GUI, PyQt en Python
Quadtree en Python --2
Python en optimisation
Métaprogrammation avec Python
Python 3.3 avec Anaconda
Géocodage en python
SendKeys en Python
Création d'interface graphique en python à l'aide de tkinter partie 1
Méta-analyse en Python
Unittest en Python
Créer une application GUI simple en Python
Époque en Python
Discord en Python
Créer des pièces de concepteur Qt avec Python (PyQt)
Allemand en Python
nCr en python
N-Gram en Python
Programmation avec Python
Plink en Python
FizzBuzz en Python
Sqlite en Python
LINE-Bot [0] en Python
CSV en Python
Assemblage inversé avec Python
Constante en Python
nCr en Python.
format en python
Scons en Python 3
Puyopuyo en python
python dans virtualenv
PPAP en Python
Quad-tree en Python
Réflexion en Python
Chimie avec Python
Hashable en Python
DirectLiNGAM en Python
LiNGAM en Python
Aplatir en Python
Aplatir en python
J'ai créé une application graphique avec Python + PyQt5
Fichier d'exécution GUI (WxPython) (pyInstaller) [Windows] dans Python3
Liste triée en Python
AtCoder # 36 quotidien avec Python
AtCoder # 2 tous les jours avec Python
Daily AtCoder # 32 en Python
Daily AtCoder # 18 en Python
Motif singleton en Python