gpt4 book ai didi

python - 为什么从 QListWidgetItem 和 QObject 派生时会崩溃

转载 作者:太空宇宙 更新时间:2023-11-03 16:11:15 28 4
gpt4 key购买 nike

以下最小示例在 Windows 上的 pyqt 5.7.1 中崩溃(将其复制粘贴到 .py 文件中并运行):

from PyQt5.QtWidgets import QListWidgetItem, QListWidget, QApplication
from PyQt5.QtCore import QObject, pyqtSlot, pyqtSignal


class MyListItem(QListWidgetItem):
def __init__(self, obj):
QListWidgetItem.__init__(self, 'example')
obj.sig_name_changed.connect(self.__on_list_item_name_changed)

def __on_list_item_name_changed(self, new_name: str):
self.setText(new_name)


class MyListItem2(QListWidgetItem, QObject):
def __init__(self, obj):
QListWidgetItem.__init__(self, 'example')
QObject.__init__(self)
obj.sig_name_changed.connect(self.pyqt_slot)

@pyqtSlot(str)
def __on_list_item_name_changed(self, new_name: str):
self.setText(new_name)


class Data(QObject):
sig_name_changed = pyqtSignal(str)


class SearchPanel(QListWidget):
def __init__(self, parent=None):
QListWidget.__init__(self, parent)
obj = Data()
hit_item = MyListItem(obj) # OK
hit_item = MyListItem2(obj) # crashes
self.addItem(hit_item)
obj.sig_name_changed.emit('new_example')


app = QApplication([])
search = SearchPanel()
search.show()
app.exec()

现在只需注释掉“崩溃”这一行,它就可以正常工作了。此外,列表小部件显示“new_example”,表明信号已通过。

有没有办法让它与 MyListItem2 一起使用?即我希望能够用 pyqtSlot 装饰插槽,这反过来又要求(在 PyQt 5.7 中)我从 QObject 派生项目。

这里的目的是列表中的每个项目都有几个可以根据来自关联数据实例的信号进行更改的特征(图标、字体、文本颜色)(每个实例实际上“存在”,在 Qt 意义上,在我们应用程序的第二个线程中)。

最佳答案

这与pyqtSlot无关。

实际问题是您试图从两个 Qt 类继承,即 not generally supported 。唯一的异常(exception)是实现接口(interface)的 Qt 类,以及共享公共(public)基类的 Qt 类(例如 QListWidgetQWidget)。然而,只有前者是官方支持的,并且关于后者有几个限制条件(此处均不相关)。

因此,从 QListWidgetItemQObject 继承的 Python 类将无法工作。当 PyQt 尝试访问未由顶级基类定义的属性时(即使该属性不存在),就会出现主要问题。在早期的 PyQt 版本中,这只会引发错误:

>>> class MyListItem2(QListWidgetItem, QObject): pass
...
>>> x = MyListItem2()
>>> x.objectName()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: could not convert 'MyListItem2' to 'QObject'
>>> x.foo
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: could not convert 'MyListItem2' to 'QObject'

这清楚地表明(用 C++ 术语来说)MyListItem2(QListWidgetItem) 不能转换为 QObject。不幸的是,似乎 PyQt5 的更新版本不再引发此错误,而是立即转储核心(这可能是一个错误)。

如果您确实需要使用pyqtSlot,一个建议是使用组合而不是子类化。所以也许是这样的:

class ListItemProxy(QObject):
def __init__(self, item, obj):
QObject.__init__(self)
self._item = item
obj.sig_name_changed.connect(self.__on_list_item_name_changed)

@pyqtSlot(str)
def __on_list_item_name_changed(self, new_name: str):
self._item.setText(new_name)

class MyListItem2(QListWidgetItem):
def __init__(self, obj):
QListWidgetItem.__init__(self, 'example')
self._proxy = ListItemProxy(self, obj)

关于python - 为什么从 QListWidgetItem 和 QObject 派生时会崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39292260/

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