网上查了下QTableView添加复选框有四种方法,都比较麻烦。
https://blog.csdn.net/liang19890820/article/details/50718340
后来看到QStandardltem有setCheckable勾选方法,就想着利用该方法,单独生成一列Checkbox显示。并在选中某一行时将Checkbox勾选上,在勾选Checkbox时自动将某一行选上。
本身Checkbox是否勾选与该行是否选择是没有关联的,要找到关联就需要借助于信号。
QItemSelectionModel在选择的单元格改变时会自动发出selectionChanged信号,所以只需要选择改变时通过槽函数OnSelectionChanged设置对应行的Checkbox。通过QItemSelection获取QModelIndex列表,然后遍历列表中所有的QModelIndex,设置对应的Checkbox状态
QModelIndexList | indexes() const | 选择范围的QModelIndex单元格列表 |
for item in selectlist.indexes():
rowNum = item.row()
# 0:Qt.Unchecked, 1:Qt.PartiallyChecked, 2:Qt.Checked
self.targetItemModel.item(rowNum, 0).setCheckState(Qt.Checked)
for item in deselectlist.indexes():
rowNum = item.row()
self.targetItemModel.item(rowNum, 0).setCheckState(Qt.Unchecked)
void | selectionChanged(const QItemSelection &selected, const QItemSelection &deselected) |
QStandardItemModel在单元格改变时会自动发出itemChanged信号,设置槽函数OnCheckBoxItemChanged处理该信号就可以进行行的选择。
需要注意的是QStandardItem可以获得行号,tableView有函数可以直接选中指定行,但是没找到不选择中指定行的函数。
于是还得根据QStandardItem找到QModelIndex,再根据QModelIndex不选择某行,不选择某行的时候需要为QItemSelectionModel.Deselect|QItemSelectionModel.Rows,否则只能不选择第一个单元格。
QModelIndex | indexFromItem(const QStandardItem *item) const | 查询指定QStandardItem的QModelIndex |
ModelIndex = self.targetItemModel.indexFromItem(item)
self.targetSelectModel.select(ModelIndex, QItemSelectionModel.Deselect|QItemSelectionModel.Rows)
void | itemChanged(QStandardItem *item) |
def initTargetView(self):
print('initTargetView')
self.targetItemModel = QStandardItemModel()
self.tableView.setModel(self.targetItemModel)
#按照行选择,可选择多行
self.tableView.setSelectionBehavior(QAbstractItemView.SelectRows)
self.tableView.setSelectionMode(QAbstractItemView.MultiSelection)
#初始化QStandardItemModel
self.LoadTarget()
#需要初始化设置QItemSelectionModel
self.targetSelectModel = QItemSelectionModel(self.targetItemModel)
self.tableView.setSelectionModel(self.targetSelectModel)
self.pushButton_add.clicked.connect(self.CreateTarget)
self.pushButton_modify.clicked.connect(self.ModifyTarget)
self.pushButton_del.clicked.connect(self.DeleteTarget)
self.tableView.doubleClicked.connect(self.OnTargetDoubleClicked)
self.targetSelectModel.selectionChanged.connect(self.OnSelectionChanged)
self.targetItemModel.itemChanged.connect(self.OnCheckBoxItemChanged)
def OnSelectionChanged(self,selectlist, deselectlist):
print('OnSelectionChanged')
#选择项改变后,遍历选择的行,将第一列设置为Qt.Checked状态,遍历未选择的行,将未选择的行设置为Qt.Unchecked状态。
for item in selectlist.indexes():
rowNum = item.row()
# 0:Qt.Unchecked, 1:Qt.PartiallyChecked, 2:Qt.Checked
self.targetItemModel.item(rowNum, 0).setCheckState(Qt.Checked)
for item in deselectlist.indexes():
rowNum = item.row()
self.targetItemModel.item(rowNum, 0).setCheckState(Qt.Unchecked)
def OnCheckBoxItemChanged(self, item):
print('OnCheckBoxItemChanged')
#对于itemChanged的单元格,获取行的行号和索引,如果该行的checkState为Checked则选择整行,如果checkState为Unchecked,则整行变为不选择。
rowNum = item.row()
ModelIndex = self.targetItemModel.indexFromItem(item)
if self.targetItemModel.item(rowNum,0).checkState() == Qt.Checked:
self.tableView.selectRow(rowNum)
elif self.targetItemModel.item(rowNum,0).checkState() == Qt.Unchecked:
self.targetSelectModel.select(ModelIndex, QItemSelectionModel.Deselect|QItemSelectionModel.Rows)
def LoadTarget(self):
print('LoadTarget')
#从数据库获取Target信息,类似表格表格数据
self.targetlist = self.returnTargetInfo()
RowNum = len(self.targetlist)
#每次导入时将Model中的数据清除,重新初始化
self.targetItemModel.clear()
#第一列没有名称,为CheckBox
self.targetItemModel.setHorizontalHeaderLabels(('', '名称', '参数1', '参数2', '参数3'))
self.tableView.verticalHeader().hide() #列表头不显示
self.tableView.horizontalHeader().setHighlightSections(False)
self.tableView.setColumnWidth(0,10) #设置各列宽度
self.tableView.setColumnWidth(1,30)
self.tableView.setColumnWidth(2,115)
self.tableView.setColumnWidth(3,85)
self.tableView.setColumnWidth(4,40)
for row in range(RowNum):
#cell为第一列,不能编辑,有勾选框可以勾选
cell = QStandardItem()
cell.setCheckable(True)
cell.setEditable(False)
self.targetItemModel.setItem(row, 0, cell)
for col in range(4):
cell = QStandardItem(str(self.targetlist[row][col + 1]))
cell.setEditable(False)
self.targetItemModel.setItem(row, col+1, cell)
self.tableView.show()