调用 QListWidgetItem 方法会给出“TypeError: native Qt signal is not callable”消息

Posted

技术标签:

【中文标题】调用 QListWidgetItem 方法会给出“TypeError: native Qt signal is not callable”消息【英文标题】:Calling a QListWidgetItem method gives a "TypeError: native Qt signal is not callable" message 【发布时间】:2014-03-09 10:33:50 【问题描述】:

我继承了一个QListWidget(名为List),它有一个名为dataChangedpyqtSignal,它在另一个基类DataWidget 中发出。实际上一切正常,但是

如果调用List 中某项(QListWidgetItem)的方法setForegroundsetTooltip,我会得到这个

TypeError: native Qt signal is not callable

消息。另一个 pyqtSignal 名为 itemLeftList 类如果不是在基类中而是在 List 类本身中发出,并且没有问题。

所以,我想知道的是:

为什么在调用列表项的方法时会出现此消息? 怎么调用方法跟那个信号有关系?! 代码有什么问题? / 我需要改变什么?

这是一个 MWE 来重现它。

from __future__ import print_function
import sys
from PyQt4.QtGui import (QMainWindow, QApplication, QFormLayout, QListWidget,
                         QListWidgetItem, QColor)
from PyQt4.QtCore import pyqtSignal

class DataWidget(object):
    """ A widget to drop data """
    def dropEvent(self, event):
        """ Emits the dataChanged signal """
        # actions to be taken on drop
        self.dataChanged.emit()

class List(QListWidget, DataWidget):
    """ List widget used for, e. g. features  """
    # This signal makes no problems
    itemLeft = pyqtSignal()
    # but this one does
    dataChanged = pyqtSignal()

    def __init__(self, parent):
        super(List, self).__init__(parent)
        self.setAcceptDrops(True)
        self.setMouseTracking(True)
        self.setSortingEnabled(True)

    def leaveEvent(self, event):
        self.itemLeft.emit()


class ApplicationWindow(QMainWindow):
    def __init__(self):
        QMainWindow.__init__(self)

        # The ListWidget
        self.list = List(self)
        self.setCentralWidget(self.list)

        self.list.itemLeft.connect(self.doOnItemLeft)
        self.list.dataChanged.connect(self.doOnDrop)

        # Adding an item to self.list
        item = QListWidgetItem('List Item Name', self.list)

        textcolor, tooltip = QColor(), None
        textcolor.setRgb(50, 50, 115)
        tooltip = 'Tool tip'
        # Calling following methods gives causes
        # TypeError: native Qt signal is not callable
        print('calling: QListWidgetItem.setForeground() for', str(item.text()))
        item.setForeground(textcolor)
        print('calling: QListWidgetItem.setToolTip() for', str(item.text()))
        item.setToolTip(tooltip)

    def doOnItemLeft(self):
        # make gui adaptions...
        print('Widget left')

    def doOnDrop(self):
        # get data from widget and so on...
        pass

app = QApplication(sys.argv)
win = ApplicationWindow()

win.show()
sys.exit(app.exec_())

版本

>>> PyQt4.pyqtconfig.Configuration().pyqt_version_str
'4.9.6'
>>> sys.version_info
sys.version_info(major=2, minor=7, micro=5, releaselevel='final', serial=0)

【问题讨论】:

也许我错了,但是 QAbstractItemView::dataChanged() 是虚拟保护槽,所以你不能在你的列表小部件上调用它。 对,QAbstractItemView 有槽 dataChanged(),因此将信号命名为相同会导致问题。给它一个不同的名字。 @vahancho 似乎可以解决它,很好的提示。我仍然想知道,为什么在调用 QListWidgetItem 方法时会出现此消息。我现在应该因为无关紧要而删除这个问题,还是有人会回答这个问题? @frankosterfeld 似乎可以解决它,很好的提示。我仍然想知道,为什么在调用 QListWidgetItem 方法时会出现此消息。我现在应该因为无关紧要而删除这个问题,还是有人会回答这个问题? embert:我的猜测是某些内部代码会尝试调用 dataChanged() 插槽,但是当您添加信号时,它会尝试调用信号。 (只是猜测)。 【参考方案1】:

正如 Vahancho 和 Osterfeld 所指出的,问题在于 QListWidget 继承自 QAbstractItemView,它定义了一个名为“dataChanged”的受保护槽:当模型中的项目发生更改时,将调用该槽,从而允许派生类 ( QListWidget 在这种情况下)采取行动。

因此创建同名信号没有意义。在列表项上调用方法setForegroundsetTooltip 会导致槽被调用,只有槽被信号覆盖,导致观察到的错误。

【讨论】:

以上是关于调用 QListWidgetItem 方法会给出“TypeError: native Qt signal is not callable”消息的主要内容,如果未能解决你的问题,请参考以下文章

使用要存储的额外数据自定义 QListWidgetItem,如何?

Qt/C++:检查 QListWidgetItem 时的信号?

如何设置QListWidgetItem的最小高度

7.5.3 QListWidgetItem条目视图介绍

QListWidgetItem 中不可见的图标

Qt学习之QListWidget删除Item