【发布时间】:2016-01-09 23:25:39
【问题描述】:
我有一段使用 PyQt4 的相当复杂的代码,有时我的信号回调根本不会运行。
这似乎与我注册回调的地点/时间有关,即。 self.someobj.somesig.connect(self.callback).
我可以在调试器中看到回调已连接并且发出了信号。
代码太大,这里就不贴了,不过我尽量总结一下:
class RC(QtCore.QObject):
render_ready = QtCore.pyqtSignal(object)
def __init__(self, pc, ...):
super(RC, self).__init__()
self.pc = pc
self.pc.rr.new_render.connect(self.insert)
def check(self):
...
if a: self.pc.replot_request.emit()
else: self.pc.render_request.emit()
def insert(self, r):
...
if b: self.render_ready.emit(r)
self.check()
class RR(QtCore.QObject):
new_render = QtCore.pyqtSignal(object)
def __init__(self, pc, app,...):
super(RR, self).__init__()
self.app = app
self.pc = pc
def run(self):
self.pc.replot_request.connect(self.on_replot_request)
self.pc.render_request.connect(self.render)
...
def render(self, scale):
...
r = R(i)
r.moveToThread(QtGui.QApplication.instance().thread())
r.new_render.emit(r)
class R(QtCore.QObject):
def __init__(self, i):
super(R, self).__init__()
...
...
class PC(QtCore.QObject):
render_request = QtCore.pyqtSignal(int)
replot_request = QtCore.pyqtSignal(object)
def __init__(self, container, app):
super(PC, self).__init__()
...
self.rr = RR(self.app)
self.rr_thread = QtCore.QThread()
self.rr.moveToThread(self.rr_thread)
self.connect(self.rr_thread, QtCore.SIGNAL("started()"), self.rr.run)
self.c = RC(self)
...
self.c.render_ready.connect(self.on_nr)
def start(self):
self.rr_thread.start()
def on_nr(self, r):
print "on_nr(...)"
class App(QtCore.QObject):
...
def __init__(self):
..
self.pc = PC(container, app)
...
self.pc.start(self) # Last thing in constructor
X = QtGui.QApplication(sys.argv)
a = App()
sys.exit(X.exec_())
我看到render_ready 连接到on_nr 并且render_ready 正在发出。但是on_nr 永远不会运行。信号序列很复杂,它跨越线程,但有问题的信号和回调在同一个线程中。此外,事件循环显然正在运行。我怎样才能开始深入挖掘?还是我犯了一些明显的错误?谢谢。
【问题讨论】:
-
我认为您需要创建一个minimal reproducible example。现在你的代码有太多未知数(例如在
RC类中你引用self.pc.r但我看不到任何地方的定义。在RR.render中你创建一个R的新实例并发出一个信号,但您在任何地方都没有R的定义) -
@three_pineapples 如果我可以创建一个MVCE,那将意味着我几乎可以自己解决问题。现在我对可能导致这种情况的原因一无所知,所以我真的不知道如何创建一个独立的问题。顺便说一句,
R只是QtCore.QObject的一个简单子类。我现在正在更新示例。 -
好吧,我还是不明白
RR.render。你创建了一个R的实例,将它移动到另一个线程(为什么?)并发出一个似乎没有连接到任何东西的信号。同时,在调用RC.insert之前不会发出RC.render_ready,当发出PC.r.new_render时会发生这种情况,但您的代码中似乎不存在该对象(PC.r)。所以我不确定你是否过于简化了你的代码,或者这是否是你问题的根本原因。我知道创建minimal reproducible example 意味着您可能会解决您的问题,但坦率地说,这就是重点。 -
所以我对标题“如何调试?”中问题的回答是制作一个minimal reproducible example。你要么意识到你做了一些愚蠢的事情,要么设法重现问题,在这种情况下,这里的人将能够解释你发现的信号、插槽和线程的任何微妙之处。
-
@three_pineapples 我修复了代码。
PC.r更改为PC.rr。我能够解决这个问题,不幸的是它与 PyQt 和信号的使用无关。我尝试了一个 MVCE,但正如我所怀疑的那样,问题没有出现,因为我没有包括原因......我还没有查明它。请看下面我的回答。无论如何,谢谢。
标签: python events pyqt signals pyqt4