Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Multithreading 线程之间未发出PyQt信号_Multithreading_Qt_Pyqt_Signals Slots_Worker - Fatal编程技术网

Multithreading 线程之间未发出PyQt信号

Multithreading 线程之间未发出PyQt信号,multithreading,qt,pyqt,signals-slots,worker,Multithreading,Qt,Pyqt,Signals Slots,Worker,我被卡住了。它应该是容易的,而且我已经使用Qt的C++ API做了很多次,但是由于某些原因,当我在PyQT中这样做时,我的几个信号/时隙中的几个不起作用(我最近从Works:Cords> QObjult在PyQt开始)。我相信它与我向/从中发送信号的独立线程有关 from PyQt4.QtCore import QThread, QObject, pyqtSignal, pyqtSlot, QTimer from PyQt4.QtGui import QApplication, QWidget,

我被卡住了。它应该是容易的,而且我已经使用Qt的C++ API做了很多次,但是由于某些原因,当我在PyQT中这样做时,我的几个信号/时隙中的几个不起作用(我最近从Works:Cords> QObjult在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()
    slot of my widget-我添加了这个,以了解为什么计时器没有触发我的工作线程的slot,但我发现它在这里也不工作
  • work()
    toggle()
    我的
    Slave
    worker类中的插槽
  • countSignal
    -它从未发出,因为我的小部件的
    viewCounter()
    插槽从未触发
我不知道我做错了什么。我已经连接了信号和插槽,启动了计时器,将其与工作线程一起移动到单独的线程,并启动了线程


我在这里遗漏了什么吗?

代码中有几个问题妨碍它正常工作

  • 根据,必须从计时器所在的线程启动(和停止)计时器。不能从其他线程启动它。如果希望计时器驻留在线程中,则应将实例化代码重新定位到
    从属对象,并在连接到线程的插槽中调用
    timer.start()
    。不过,在这里您确实需要小心,因为
    从线程仍将在主线程中运行。或者,您可以将计时器留在主线程中

  • setupConn()
    完成后,
    slave
    timer
    将被垃圾收集。将它们存储为
    self.slave
    self.timer
    。(或者,您应该能够为它们指定一个父对象,但这似乎会导致应用程序在退出时崩溃,所以最好还是将它们存储为实例属性)

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


  • 谢谢我忘了计时器。这是这里的主要问题。对于增量……(FAUPALM)…YEAP,它从不递增:D BTW用于<代码>自己。从< <代码> >代码> >:自拍:<代码> >我也认为它已经超出了范围,但是我习惯了C++版本,在这里,您正在传递一个指针,指向这两个线程,我没有想到这里会改变这个。但我有一个问题——在C++中,如果要把这些东西移到另一个线程,那么创建类成员是不正确的。我想Python不是这样的?这难道不会导致
    QObject.deleteLater()
    毫无意义吗?@rbaleksandar这可能不是一个好的做法(尽管我不确定替代方案是什么),但在Python中这样做从根本上讲没有什么错。它只是对C++对象的引用。代码> DELTETELATAL()/CUT>仍然有效,如果您尝试通过剩余引用删除QT对象,则会得到一个警告,通知终端正在删除的C++对象。C++中,如果使用类成员,它将(我现在无法正确地记住下面哪一个会发生)要么失败,要么信号处理不当,最终将在错误的线程中发射/捕获。这就是为什么我没有使用<代码>自己/代码>,但是在Python中传递参数的方式与C++中的参数有点不同(就控制是否通过引用或值而言)。如果slave和timer是小部件类的一部分(在我的例子中),那么一旦小部件被销毁,它也应该销毁它的所有成员,包括这两个。HyM.M.RbaleKeStAddioPython,当Python窗口小类被垃圾收集时,Python指针将被删除,但是C++对象本身只会被垃圾收集,如果没有其他引用C++,它们就没有QT相关的父类。我认为只要你把Qt C++对象和Python引用当作只有耦合的,你就能看到什么是有效的,什么是不存在的。就线程中对象的信号连接而言,这可能很有趣:这很有意义。谢谢你的链接页面。现在就看。