【问题标题】:connect() failed between selectionChanged and my pyQtSlot after updating from Qt4 to Qt5从 Qt4 更新到 Qt5 后 selectionChanged 和我的 pyQtSlot 之间的 connect() 失败
【发布时间】:2021-07-15 22:35:24
【问题描述】:

我最近参与了一个使用 PyQt 的项目。它使用的是 Qt4,但由于在最新系统上安装它以及所有其他工具和包的痛苦,我决定将所有内容更新到 Python3、Qt5 等。

在旧代码中,

self.selectionModel().selectionChanged.connect(self.selection_changed_event)

有效且有效。

@QtCore.pyqtSlot("QTreeView, QItemSelection, QItemSelection")
    def selection_changed_event(self, selected, deselected):
        """Event handler.
        Triggered by TreeView selection change.
        Get Title from selected/deselected items. Send SelectionEvent(title) to widgets to show/hide content as needed.
        :param selected: New selected item.
        :param deselected: Item that was selected.
        :return:
    """

自从更新到 Qt5,现在说 connect() 失败了。虽然我是个菜鸟,但我的理解是我确实想检索视图的selectionModel,然后连接到它的selectionChanged 信号。所以我应该有self.ITEM.selectionModel().selectionChanged.connect(self.SLOT)的形式。 在插槽内,它似乎符合标准,我应该有 QModelIndex 告诉活动期间选择的内容和 QModelIndex 告诉活动期间取消选择的内容。

因此,我对此所做的唯一其他值得注意的更改是从 QTGui 切换到 QtWidget。这是因为 QtGui 和 QtWidget 从 Qt4 转移到 Qt5。

旧:

class QMenuTreeView(QtGui.QTreeView):
    selectionChangeEvent = QtCore.pyqtSignal(str)
    def __init__(self, parent=None, log=None):
        QtGui.QTreeView.__init__(self, parent)
        self.parent = parent
        ...
        self.selectionModel().selectionChanged.connect(self.selection_changed_event)

新:

class QMenuTreeView(QtWidgets.QTreeView):
    selectionChangeEvent = QtCore.pyqtSignal(str)
    def __init__(self, parent=None, log=None):
        QtWidgets.QTreeView.__init__(self, parent)
        self.parent = parent
        ...             
        self.selectionModel().selectionChanged.connect(self.selection_changed_event)

Qt4 和 QT5 之间是否还有其他我不理解的变化,并且会导致这种情况? 看来我不能使用 QtGui,因为对 QTreeView 的引用不再有效,此外,它现在在他们的文档中列为 QtWidgets。还有什么我需要转换的,还是这个 connect() 问题与其他问题有关?

【问题讨论】:

    标签: python-3.x pyqt5 pyqt4 qwidget qtreeview


    【解决方案1】:

    pyqtSlot 语法似乎是错误的(即使对于 PyQt4):签名应该包含视图的类,因为它不是信号的一部分。
    它在 PyQt4 上工作的原因是,在那个版本中,槽装饰器语法和类型检查不如 PyQt5 严格。

    考虑到,在正常情况下,应该不需要插槽装饰器(尤其是对于“通用”小部件和不处理线程时),所以我会立即删除装饰器,至少通过注释它.

    那么,如果确实需要该特定要求,则语法应为:

        @QtCore.pyqtSlot(QtCore.QItemSelection, QtCore.QItemSelection)
        def selection_changed_event(self, selected, deselected):
            # ...
    

    请注意,没有引号,它们仅在 PyQt 不提供类型并且插槽无论如何都需要它们的非常特定情况下需要它们(例如,QStringList)。此外,参数的连接应该在同一个字符串中。

    这被正确调用并打印两个选择(注意:

        @pyqtSlot('QItemSelection', 'QItemSelection'):
        def test(self, selected, deselected):
            print(selected, deselected)
    

    这引发了一个异常,因为槽只识别第一种类型,但函数需要两种:

        @pyqtSlot('QItemSelection, QItemSelection')
        def test(self, selected, deselected):
            print(selected, deselected)
    

    最后,这是可行的,但只给出了第一个参数:

        @pyqtSlot('QItemSelection, QItemSelection')
        def test(self, *args):
            print(args)
    

    【讨论】:

    • 有趣。对此发表评论似乎已经清除了该错误。我认为它保持这种方式是为了帮助处理一些可能会被使用的 C++ 东西。因为他们有一些 QT 类的自定义版本,所以也做了一些奇怪的事情。谢谢!
    • @CNK13 使用 pyqtSlot 本身不是问题,而且,如前所述,在某些情况下需要它,而通常是否使用它们并不会真正改变这件事。关键是该语法首先是错误的,使得它们的使用完全没有意义。并且子类化 Qt 类根本不是问题,这对于 Qt 和 PyQt 来说都是很正常的。无论如何,请记住,如果某个答案解决了您的问题,您应该通过单击其左侧的灰色勾号将其标记为已接受。
    • 我的猜测是他们试图解释“自我”类型,因此“QTreeView,QItemSelection,QItemSelection”我不太理解将它们全部放在一个字符串中的最初想法。 . 将它们分开并删除“自我”类型似乎符合预期。
    猜你喜欢
    • 2013-06-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多