是否可以从基类继承信号,并在派生类中连接方法?如果是,如何实现?
使用组合的工作测试案例
在MyWidget
中实例化一个MyObject
,并在小部件中对由对象发出的信号做出反应。
from PySide.QtGui import QApplication, QMainWindow
from PySide.QtCore import QObject, QTimer, Signal
from PySide.QtGui import QLabel
class MyObject(QObject):
sig = Signal()
def __init__(self, parent=None):
super().__init__(parent)
QTimer.singleShot(3000, self.alert)
QTimer.singleShot(5000, self.exit)
def alert(self):
self.sig.emit()
def exit(self):
print('All done')
exit(0)
class MyWidget(QLabel):
def __init__(self, parent=None):
super().__init__(parent)
self.monitor = MyObject(self)
self.monitor.sig.connect(self.update)
def update(self):
print(2)
app = QApplication([])
w = MyWidget()
w.show()
app.exec_()
这是一个小而实用的示例,它打开了一个最小的、空白的窗口,由控件实例化的
self.monitor
对象在 3 秒和 5 秒后发出计时器信号。第一个信号提示控件将一个数字打印到控制台,第二个信号导致应用程序退出。
继承失败的测试用例
对于继承,只需更改控件类:class MyWidget(MyObject, QLabel):
def __init__(self, parent=None):
super().__init__(parent)
self.sig.connect(self.update)
def update(self):
print(2)
如果在控制台中运行此代码,将不会打印任何输出,但会出现分段错误。为什么?这个问题能解决吗?
通过替换 super()
来修复
有趣的是,如果两个类都改为不使用 super()
,则示例代码将再次正常工作:
class MyObject(QObject):
sig = Signal()
def __init__(self, parent=None):
QObject.__init__(self, parent)
QTimer.singleShot(3000, self.alert)
QTimer.singleShot(5000, self.exit)
def alert(self):
self.sig.emit()
def exit(self):
print('All done')
exit(0)
class MyWidget(MyObject, QLabel):
def __init__(self, parent=None):
MyObject.__init__(self, parent)
QLabel.__init__(self, parent)
self.sig.connect(self.update)
def update(self):
print(2)
通常我更喜欢使用super()
,但也许我需要重新考虑一下?我特意链接了两篇关于在Python中使用super()
的有争议的文章。现在我对如何在pyside中正确使用super()
或者为什么它根本不起作用感兴趣。
小更新:
当使用继承和super()
,但删除所有与信号相关的代码时,示例可以正常工作,即打开窗口并且不会崩溃。因此,似乎存在一些迹象表明super()
初始化和信号的组合会导致问题。
小更新2:
..并且当注释掉self.sig.connect
时,窗口启动并且只有在5秒信号触发退出应用程序时才会崩溃。
(这是在Ubuntu 13.04系统上使用Qt 4.8.4,Pyside 1.1.2和CPython 3.3.1解释器)
sig.connect()
就足够了,因为信号应该是类级别而不是实例化级别属性。 - tacaswellpyside
对象只是C++对象的薄包装器,它们的实例化被搞砸了。我对super
的理解是,它就像C++中的const正确性一样,如果你在每个地方都使用它,它会非常好用,但如果你只有时候使用它,它会带来很大的痛苦。 - tacaswellQLabel
,它会正常工作。 - tacaswell