如何在PyQt4中为QTreeWidget实现itemChecked和itemUnchecked信号?

时间:2012-12-01 17:49:43

标签: qt pyqt pyqt4 signals-slots qtreewidget

QTreeWidget上的信号itemChecked和itemUncheсked在哪里?

Qt Signals: (quote from PyQt4 QTreeWidget documentation page)

void currentItemChanged (QTreeWidgetItem *,QTreeWidgetItem *)
void itemActivated (QTreeWidgetItem *,int)
void itemChanged (QTreeWidgetItem *,int)
void itemClicked (QTreeWidgetItem *,int)
void itemCollapsed (QTreeWidgetItem *)
void itemDoubleClicked (QTreeWidgetItem *,int)
void itemEntered (QTreeWidgetItem *,int)
void itemExpanded (QTreeWidgetItem *)
void itemPressed (QTreeWidgetItem *,int)
void itemSelectionChanged ()

目前我解决了这个问题:

self.treeWidget.itemClicked.connect (self.handle)

def handle (item, column): 
    print 'emitted!', item.text(column)
    if item.checkState(column) == QtCore.Qt.Checked:
        # there are a lot of my functions inside which work with item data
        self.handleChecked(item, column)
    elif item.checkState(column) == QtCore.Qt.Unchecked:
        self.handleUnchecked(item, column)

但这对我来说是一个糟糕的解决方案,因为itemClicked在很多情况下都会发出。它是在项目文本的左/右鼠标点击的情况下发出的,这是绝对不必要的(我在self.handleChecked中有很重的功能,在上下文菜单打开时不必要的调用它们非常糟糕)。

好吧,我也尝试使用itemChanged

self.treeWidget.itemChanged.connect (self.handle)

但这种情况更糟糕! self.handle函数将自己递归调用到无穷大以及更远,因为我在self.handleChecked中的函数更改了项目数据,并且此信号一次又一次地发出。此外,我需要仅在项目复选框切换时发出的信号。

有人可以告诉我,我做错了吗?

2 个答案:

答案 0 :(得分:10)

为避免在使用itemChanged信号时出现递归问题,请暂时尝试blocking signals,直到处理程序完成:

def handle(self, item, column):
    self.treeWidget.blockSignals(True)
    if item.checkState(column) == QtCore.Qt.Checked:
        self.handleChecked(item, column)
    elif item.checkState(column) == QtCore.Qt.Unchecked:
        self.handleUnchecked(item, column)
    self.treeWidget.blockSignals(False)

<强>更新

问题的另一部分询问是否仅在检查项目时发出信号。

这样做的一种方法是继承QTreeWidgetItem并重新实现它的setData函数:

class TreeWidgetItem(QtGui.QTreeWidgetItem):
    def setData(self, column, role, value):
        state = self.checkState(column)
        QtGui.QTreeWidgetItem.setData(self, column, role, value)
        if (role == QtCore.Qt.CheckStateRole and
            state != self.checkState(column)):
            treewidget = self.treeWidget()
            if treewidget is not None:
                treewidget.itemChecked.emit(self, column)

class Window(QtGui.QTreeWidget):
    itemChecked = QtCore.pyqtSignal(object, int)

    def __init__(self, rows, columns):
        QtGui.QTreeWidget.__init__(self)
        self.itemChecked.connect(self.handleItemChecked)

    def handleItemChecked(self, item, column):
        print 'ItemChecked', int(item.checkState(column))

答案 1 :(得分:0)

要完成@ekhumoro的回答, 并给出一个简短的答案(不继承QTreeWidgetItem的子类): 阻止信号:

self.treeWidget.blockSignals(True)
self.treeWidget.blockSignals(False)

并使用

self.treeWidget.itemChanged

连接到所需的内容。 更改数据时使用信号(内部文本,检查状态等) 并在链接到此信号的函数中,验证treeWidget是否已更改为选中状态。