Sto leggendo attraverso alcuni documenti su PyQt5 per trovare un semplice meccanismo di slot del segnale. Mi sono fermato a causa di una considerazione di progettazione.PyQt uso corretto di emit() e pyqtSignal()
Si consideri il seguente codice:
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_())
per tenere traccia delle modifiche apportate al dispositivo di scorrimento, ho semplicemente Print and log le modifiche apportate. Quello che non mi piace del codice è che sono obbligato a chiamare lo slot sld.valueChanged
tre volte per inviare le stesse informazioni a 3 diversi slot.
È possibile creare il mio pyqtSignal
che invia un numero intero a una singola funzione di alloggiamento. E a turno la funzione slot emette i cambiamenti che devono essere apportati?
- Forse non capisco pienamente lo scopo di
emit()
perché non ci sono buoni esempi del suo scopo nel PyQt Signal-Slot docs. Tutto quello che ci viene dato è un esempio di come implementare unoemit
senza parametri.
Quello che mi piacerebbe fare è creare una funzione che gestisca la funzione di emissione. Considera quanto segue:
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_())
Ci sono ovviamente alcuni difetti di progettazione importanti qui. Non riesco a capovolgere l'ordine delle chiamate di funzione. E non sto implementando correttamente pyqtSignal
. Tuttavia, ritengo che affermare correttamente i seguenti 3 punti mi aiuterà a produrre un'app corretta:
- Per un segnale predefinito: inviare il segnale alla funzione di slot. Lo slot può essere reimplementato per utilizzare i valori del segnale.
- Produce l'oggetto
pyqtSignal
con alcuni parametri. Non è ancora chiaro quale sia lo scopo di questi parametri e in che modo si differenziano dai parametri "emetti". emit
può essere reimplementato per inviare valori di segnale specifici alla funzione di slot. Inoltre, non è ancora chiaro il motivo per cui avrei bisogno di inviare valori diversi dai metodi di segnale precedentemente esistenti.
Sentitevi liberi di modificare completamente il codice per quello che sto cercando di fare perché non ho ancora capito se è nel regno del buon stile.
Sembra che commentare "@pyqtSlot (int)" non influenzi l'output. Perché è così? – Max
Sembra che il vero scopo del decoratore consenta troppo il sovraccarico. – Max
Non è solo per sovraccaricare. Questa [risposta] (http://stackoverflow.com/a/14431607/1547004) lo spiega abbastanza bene. Se invii segnali attraverso i thread, richiede anche il decoratore di slot. –