我被困住了。这应该很容易,并且我使用Qt的C ++ API进行了很多次,但是由于某些原因,当我在PyQt中执行此操作时,我的一些信号/插槽无法正常工作(我最近开始使用worker的概念QObject
在PyQt中)。我相信它必须与我向/从我发出信号的单独线程做些事情。
from PyQt4.QtCore import QThread, QObject, pyqtSignal, pyqtSlot, QTimer
from PyQt4.QtGui import QApplication, QWidget, QVBoxLayout, QPushButton, QLabel
class Slave(QObject):
countSignal = pyqtSignal(int)
def __init__(self, parent = None):
super(Slave, self).__init__()
self.toggleFlag = False
self.counter = 0
@pyqtSlot()
def work(self):
if not self.toggleFlag: return
if self.counter > 10: self.counter = 0
self.counter += self.counter
self.countSignal.emit(self.counter)
@pyqtSlot()
def toggle(self):
self.toggleFlag = not self.toggleFlag
class Master(QWidget):
toggleSignal = pyqtSignal()
def __init__(self, parent = None):
super(Master, self).__init__()
self.initUi()
self.setupConn()
def __del__(self):
self.thread.quit()
while not self.thread.isFinished(): pass
def initUi(self):
layout = QVBoxLayout()
self.buttonToggleSlave = QPushButton('Start')
self.labelCounterSlave = QLabel('0')
layout.addWidget(self.buttonToggleSlave)
layout.addWidget(self.labelCounterSlave)
self.setLayout(layout)
self.show()
def setupConn(self):
self.thread = QThread()
slave = Slave()
timer = QTimer()
timer.setInterval(100)
# Make sure that both objects are removed properly once the thread is terminated
self.thread.finished.connect(timer.deleteLater)
self.thread.finished.connect(slave.deleteLater)
# Connect the button to the toggle slot of this widget
self.buttonToggleSlave.clicked.connect(self.toggle)
# Connect widget's toggle signal (emitted from inside widget's toggle slot) to slave's toggle slot
self.toggleSignal.connect(slave.toggle)
# Connect timer's timeout signal to slave's work slot
timer.timeout.connect(slave.work)
timer.timeout.connect(self.timeout)
# Connect slave's countSignal signal to widget's viewCounter slot
slave.countSignal.connect(self.viewCounter)
# Start timer
timer.start()
# Move timer and slave to thread
timer.moveToThread(self.thread)
slave.moveToThread(self.thread)
# Start thread
self.thread.start()
@pyqtSlot(int)
def viewCounter(self, value):
print(value)
self.labelCounterSlave.setText(str(value))
@pyqtSlot()
def toggle(self):
print("Toggle called")
self.buttonToggleSlave.setText("Halt" if (self.buttonToggleSlave.text() == "Start") else "Start")
self.toggleSignal.emit()
@pyqtSlot()
def timeout(self):
print("Tick")
if __name__ == "__main__":
app = QApplication([])
w = Master()
w.setStyleSheet('cleanlooks')
app.exec_()
不触发/发出以下事件:
timeout()
我的小部件的广告位-我添加了此信息,以查看为什么计时器未触发我的工作人员的广告位,但我发现它在这里也不起作用...work()
和toggle()
我的Slave
工人阶级中的插槽countSignal
-因为我的小部件的viewCounter()
插槽从未被触发过,所以它永远不会发出我不知道我在做什么错。我已经连接了信号和插槽,启动了我的计时器,将它与工作程序一起移到我的单独线程中并启动了线程。
我在这里想念什么吗?
该代码存在多个问题,导致其无法正常工作。
根据文档,您必须从其驻留的线程中启动(和停止)计时器。不能从另一个线程中启动计时器。如果要使计时器驻留在线程中,则应将实例化代码重新定位到Slave
对象,并timer.start()
在连接到线程started
信号的插槽中调用。不过,您确实需要小心,因为该Slave.__init__
方法仍将在主线程中运行。或者,您可以只将计时器留在主线程中。
slave
并timer
在setupConn()
完成时被垃圾收集。将它们存储为self.slave
和self.timer
。(或者,您应该能够为其指定父项,但这似乎会导致应用程序退出时崩溃,因此最好坚持将它们存储为实例属性)。
我认为这条线self.counter += self.counter
真的应该是self.counter += 1
吗?否则计数器永远不会增加:)
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句