如何检查QTreeWidget中的复选框是否被选中或未选中?
我写了下面的代码:
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 个回答
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()
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')