PyQt bonne utilisation de l'emit() et pyqtSignal()
Je suis de lecture par le biais de la documentation sur PyQt5 à venir avec un simple signal-slot mécanisme. Je suis venu à un arrêt dû à un facteur de conception.
Considérons le code suivant:
import sys
from PyQt5.QtCore import (Qt, pyqtSignal)
from PyQt5.QtWidgets import (QWidget, QLCDNumber, QSlider,
QVBoxLayout, QApplication)
class Example(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def printLabel(self, str):
print(str)
def logLabel(self, str):
'''log to a file'''
pass
def initUI(self):
lcd = QLCDNumber(self)
sld = QSlider(Qt.Horizontal, self)
vbox = QVBoxLayout()
vbox.addWidget(lcd)
vbox.addWidget(sld)
self.setLayout(vbox)
#redundant connections
sld.valueChanged.connect(lcd.display)
sld.valueChanged.connect(self.printLabel)
sld.valueChanged.connect(self.logLabel)
self.setGeometry(300, 300, 250, 150)
self.setWindowTitle('Signal & slot')
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
De suivre les modifications apportées à la barre, il me suffit d'imprimer et d'enregistrer les modifications apportées. Ce que je n'aime pas sur le code, c'est que je suis obligé d'appeler le sld.valueChanged
fente trois fois pour envoyer la même information à 3 machines différentes.
Est-il possible de créer mon propre pyqtSignal
qui envoie un nombre entier à un seul logement de fonction. Et, en retour, le logement de fonction émettent les changements qui doivent être faits?
- Peut-être que je ne comprends pas tout à la fin de
emit()
car il n'y a pas de bons exemples de but dans la PyQt Signal-Slot docs. Tous nous nous sommes donné est un exemple de la façon de mettre en œuvre unemit
sans paramètres.
Ce que je voudrais faire est de créer une fonction qui gère le émettent de la fonction. Considérez les points suivants:
import sys
from PyQt5.QtCore import (Qt, pyqtSignal)
from PyQt5.QtWidgets import (QWidget, QLCDNumber, QSlider,
QVBoxLayout, QApplication)
class Example(QWidget):
def __init__(self):
super().__init__()
#create signal
self.val_Changed = pyqtSignal(int, name='valChanged')
self.initUI()
def initUI(self):
lcd = QLCDNumber(self)
sld = QSlider(Qt.Horizontal, self)
vbox = QVBoxLayout()
vbox.addWidget(lcd)
vbox.addWidget(sld)
self.setLayout(vbox)
sld.val_Changed.connect(self.handle_LCD)
self.val_Changed.emit()
self.setGeometry(300, 300, 250, 150)
self.setWindowTitle('Signal & slot')
self.show()
def handle_LCD(self, text):
'''log'''
print(text)
'''connect val_Changed to lcd.display'''
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
Il existe évidemment des graves défauts de conception ici. Je ne peut pas envelopper la tête autour de l'ordre des appels de fonction. Et je ne suis pas la mise en œuvre de pyqtSignal
correctement. Je suis toutefois convaincu que correctement libellée 3 points va m'aider à produire une bonne application:
- De prédéfinir un signal: permet d'envoyer le signal vers le logement de fonction. La fente peut être réimplémentée à utiliser les valeurs du signal.
- Produire
pyqtSignal
objet avec certains paramètres. Il n'est pas encore clair quel est le but de ces paramètres sont et comment ils diffèrent des "émettent " paramètres". emit
peut être réimplémentée à envoyer de signal spécifique de valeurs pour le logement de fonction. Il n'est pas encore clair pourquoi j'aurais besoin d'envoyer des différentes valeurs précédemment existante signal de méthodes.
Hésitez pas à complètement modifier le code pour ce que je suis en train de faire parce que je n'ai pas encore compris si son dans le domaine de bon style.
OriginalL'auteur Max | 2016-04-05
Vous devez vous connecter pour publier un commentaire.
Vous pouvez définir votre propre logement (tout python "callable") et de se connecter au signal, puis d'appeler les autres machines à sous de que un logement.
Aussi, si vous souhaitez définir votre propre signal, ils doivent être définis comme des variables de classe
Les arguments pour
pyqtSignal
définir les types d'objets qui serontemit
'd sur ce signal, dans ce cas, vous pourriez faireEn général, vous ne devriez pas être en émettant de la construction dans les signaux. Vous aurez uniquement besoin d'émettre les signaux que vous définissez. Lors de la définition d'un signal, vous pouvez définir différentes signatures de différents types, et des fentes peuvent choisir signature ils veulent se connecter. Par exemple, vous pourriez faire ce
Cela permettra de définir un signal avec deux signatures différentes, et un slot peut se connecter à un
Dans la pratique, j'ai rarement surcharge de signal de signatures. Je devrais normalement il suffit de créer deux signaux distincts avec des signatures différentes plutôt que de surcharger le même signal. Mais elle existe et est pris en charge dans PyQt parce que Qt a des signaux qui sont surchargés de cette façon (par exemple.
QComboBox.currentIndexChanged
)@pyqtSlot(int)
n'a pas d'effet sur la sortie. Pourquoi est-ce le cas?Il semble que le véritable but de le décorateur est aussi de permettre la surcharge fins.
Ce n'est pas seulement pour la surcharge. Cette répondre explique assez bien. Si jamais vous êtes en envoyant des signaux à travers les fils, il exige la fente décorateur, trop.
Une simple note de côté: parce que
my_signal
est un attribut de la classe et non associé à une QWidget. Ce qui est bon Qt de style pour la création de quelque chose commeself.lcd.my_signal.connect(on_my_signal)
.Si vous souhaitez ajouter un signal à l'écran LCD widget, vous aurez besoin de sous-classe et de l'ajouter comme un attribut de classe. Vous ne devrait pas émettre le signal à partir de n'importe où, mais à l'intérieur de la classe, de sorte qu'il n'a pas vraiment de sens d'ajouter des signaux non-sous-classé widgets
OriginalL'auteur Brendan Abel