如何检查复选框是否被选中或取消选中?(在QTreeWidget中)

4
我已经编写了以下代码:
from PyQt4 import QtCore, QtGui
import sys

class window(QtGui.QMainWindow):
    def __init__(self, parent=None):
        super(window, self).__init__(parent)
        self.TreeWidget = QtGui.QTreeWidget()
        self.TreeWidget.setColumnCount(1)
        item1 = QtGui.QTreeWidgetItem(["Item 1"])
        item1.setCheckState(0, QtCore.Qt.Checked)
        item2 = QtGui.QTreeWidgetItem(["Item 2"])
        item2.setCheckState(0, QtCore.Qt.Unchecked)
        item3 = QtGui.QTreeWidgetItem(["Item 3"])
        item3.setCheckState(0, QtCore.Qt.Unchecked)
        self.TreeWidget.addTopLevelItem(item1)
        self.TreeWidget.addTopLevelItem(item2)
        self.TreeWidget.addTopLevelItem(item3)
        self.setCentralWidget(self.TreeWidget)

        if item1.checkState(0) == QtCore.Qt.Checked:
            print('item 1 is checked')
        if item2.checkState(0) == QtCore.Qt.Checked:
            print('item 2 is checked')
        if item3.checkState(0) == QtCore.Qt.Checked:
            print('item 3 is checked')

if __name__ == "__main__":
    import sys
    app = QtGui.QApplication(sys.argv)
    ui = window()
    ui.show()
    sys.exit(app.exec_())

使用上述代码,我成功地创建了可勾选的框。但是当用户勾选某个项目时,我希望在运行程序时打印出已勾选的项目。据我所知,我需要使用一个事件或信号,但我不确定如何设置信号。我找到了一个示例代码,展示了使用MousePressEvent的用法,但我不确定如何使用Python实现该代码。
#include <QtGui>

class TreeWidget : public QTreeWidget
{
public:
        TreeWidget()
        {
                setColumnCount(1);
                item1 = new QTreeWidgetItem(this);
                item1->setExpanded(true);
                item1->setFlags(item1->flags() | Qt::ItemIsUserCheckable);
                item1->setCheckState(0, Qt::Checked);
                item1->setText(0, "item 1");

                item2 = new QTreeWidgetItem(item1);
                item2->setFlags(item2->flags() | Qt::ItemIsUserCheckable);
                item2->setCheckState(0, Qt::Checked);
                item2->setText(0, "item 2");

                item3 = new QTreeWidgetItem(this);
                item3->setText(0, "item 3");
                item3->setFlags(item3->flags() | Qt::ItemIsUserCheckable);
                item3->setCheckState(0, Qt::Checked);

        }
        void mousePressEvent(QMouseEvent *event)
        {
                QModelIndex indexClicked = indexAt(event->pos());
                if(indexClicked.isValid()) {
                        QRect vrect = visualRect(indexClicked);
                        int itemIndentation = vrect.x() - visualRect(rootIndex()).x();
                        QRect rect = QRect(header()->sectionViewportPosition(0) + itemIndentation
                                , vrect.y(), style()->pixelMetric(QStyle::PM_IndicatorWidth), vrect.height());
                        if(rect.contains(event->pos())) {
                                qDebug() << "checkbox clicked";
                                QTreeWidget::mousePressEvent(event);
                                return;
                        } else {
                                QTreeWidget::mousePressEvent(event);
                        }}}
private:
        QTreeWidgetItem *item1;
        QTreeWidgetItem *item2;
        QTreeWidgetItem *item3;
        QTreeWidgetItem *item4;
};

int main(int argc, char **argv)
{
        QApplication app(argc, argv);
        TreeWidget box;
        box.show();
        return app.exec();
}
2个回答

2
使用 itemClicked 信号:
class window(QtGui.QMainWindow):
    def __init__(self, parent=None):
        super(window, self).__init__(parent)
        self.TreeWidget = QtGui.QTreeWidget()
        self.TreeWidget.setColumnCount(1)
        # self.item1/2/3 = ....  save reference to the items
        #   to access them in the callback (check_status)
        item1 = self.item1 = QtGui.QTreeWidgetItem(["Item 1"])
        item1.setCheckState(0, QtCore.Qt.Checked)
        item2 = self.item2 = QtGui.QTreeWidgetItem(["Item 2"])
        item2.setCheckState(0, QtCore.Qt.Unchecked)
        item3 = self.item3 = QtGui.QTreeWidgetItem(["Item 3"])
        item3.setCheckState(0, QtCore.Qt.Unchecked)
        self.TreeWidget.addTopLevelItem(item1)
        self.TreeWidget.addTopLevelItem(item2)
        self.TreeWidget.addTopLevelItem(item3)
        self.setCentralWidget(self.TreeWidget)

        # connect the itemClicked signal to the callback check_status.
        self.TreeWidget.itemClicked.connect(self.check_status)

    def check_status(self):
        if self.item1.checkState(0) == QtCore.Qt.Checked:
            print('item 1 is checked')
        if self.item2.checkState(0) == QtCore.Qt.Checked:
            print('item 2 is checked')
        if self.item3.checkState(0) == QtCore.Qt.Checked:
            print('item 3 is checked')

1
键盘的空格键可以触发复选框,但代码会忽略此事件。 - Ruben Kazumov

0
复选框是字段中的一种值。它与文本不同,但仍然是值。 可以使用鼠标事件或键盘事件(空格键)触发复选框。因此,识别这种事件的最简单方法是子类化QTreeWidgetItem并将最后一个复选框状态存储为QtCore.Qt.CheckState类型的变量。
请考虑以下代码片段:
from __future__ import annotations
from PyQt5.QtWidgets import *
from PyQt5.QtCore import * 
from PyQt5.QtGui import * 
import sys, typing

class MyTree(QTreeWidget):

    class MyItem(QTreeWidgetItem):
        def __init__(self, parent):
            super().__init__(parent)
            # Assuming, that an element has only one checkbox
            # 
            self.storedCheckedState: QtCore.Qt.CheckState = self.checkState(0)
            # Otherwise, we need more stored variables here

        def setCheckState(self, column: int, state: QtCore.Qt.CheckState) -> None:
            # The chekbox in the first column:
            if column == 0:
                self.storedCheckedState = state
            return super().setCheckState(column, state)

    def __init__(self, parent: typing.Optional[QWidget]=None) -> None:
        super().__init__(parent=parent)
        self.setColumnCount(4)
        header = MyTree.headerItem(self)
        header.setText(1, 'A')
        header.setText(2, 'B')
        header.setText(3, 'C')
        header.setText(4, 'D')

    def changed(self, item:MyTree.MyItem, column:int) -> None:
        if column == 0:
            if item.storedCheckedState != item.checkState(0):
                print("Item checked!")
                item.storedCheckedState = item.checkState(0)
            else:
                print("Item edited, but not checked!")
        else:
            print("Some field edited...")
        


    def loadData(self, data:typing.Any) -> None:
        # stop events propagation
        try:
            self.disconnect()
        except:
            pass
        # Load the data there...
        # In this particular case, 
        # the tree will be simply generated:
        # 
        # [ ] Parent 1
        #     [ ] Child 1
        #     [ ] Child 2
        #     [ ] Child 3
        # ...
        for i in range(3):
            # parent = QTreeWidgetItem(tree)
            parent = MyTree.MyItem(self)
            parent.setText(0, "Parent {}".format(i))
            parent.setFlags(parent.flags() | Qt.ItemIsTristate | Qt.ItemIsUserCheckable | Qt.TextEditable | Qt.ItemIsEditable)
            for x in range(5):
                child = MyTree.MyItem(parent)
                child.setFlags(child.flags() | Qt.ItemIsUserCheckable | Qt.TextEditable | Qt.ItemIsEditable)
                child.setText(0, "Child {}".format(x))
                child.setCheckState(0, Qt.Unchecked)

        # restore events propagation
        self.itemChanged.connect(self.changed)


def main(): 
    app = QApplication (sys.argv)
    tree = MyTree()    
    tree.loadData("ANY DATA")
    tree.show() 
    sys.exit(app.exec_())

if __name__ == '__main__':
    main()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接