gpt4 book ai didi

multithreading - 未发出线程之间的 PyQt 信号

转载 作者:行者123 更新时间:2023-12-03 12:46:02 24 4
gpt4 key购买 nike

我卡住了。这应该很容易,我已经使用 Qt 的 C++ API 完成了很多次,但是由于某种原因,当我在 PyQt 中执行此操作时,我的几个信号/插槽无法正常工作(我最近开始使用 worker 的概念PyQt 中的 QObject)。我相信它必须对我向/从发出信号的单独线程做一些事情。

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() 我的小部件的插槽 - 我添加这个是为了看看为什么计时器没有触发我的 worker 的插槽,但我发现它在这里也不起作用......
  • work()toggle() 我的 Slave worker 类中的插槽
  • countSignal - 它永远不会发出,因为我的小部件的 viewCounter() 槽从未被触发

我不知道我做错了什么。我已经连接了信号和槽,启动了我的计时器,将它与 worker 一起移动到我的单独线程并启动了线程。

我是不是漏掉了什么?

最佳答案

代码中存在多个问题,导致其无法正常工作。

  1. 根据 documentation ,您必须从它所在的线程启动(和停止)计时器。您不能从另一个线程启动它。如果你想让定时器驻留在线程中,你应该将实例化代码重新定位到 Slave 对象,并在连接到线程的槽中调用 timer.start() 开始 信号。你在这里确实需要小心,因为 Slave.__init__ 方法仍将在主线程中运行。或者,您可以将计时器留在主线程中。

  2. setupConn() 完成时,
  3. slavetimer 正在被垃圾回收。将它们存储为 self.slaveself.timer。 (或者,您应该能够为它们指定父级,但这似乎会导致应用程序在退出时崩溃,因此最好坚持将它们存储为实例属性)。

  4. 我假设行 self.counter += self.counter 真的应该是 self.counter += 1?否则计数器永远不会递增:)

关于multithreading - 未发出线程之间的 PyQt 信号,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35398165/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com