我想向某些QTableView行中的特定单元格添加一个委托QComboBox委托。我发现了几篇有关如何添加委托的文章,但没有关于使用QComboBox选择项更新单元的示例。
这是我到目前为止所拥有的:
main.ui
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Dialog</class>
<widget class="QDialog" name="Dialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>350</width>
<height>239</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<widget class="QWidget" name="formLayoutWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>341</width>
<height>231</height>
</rect>
</property>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="1">
<widget class="QPushButton" name="btnPopulate">
<property name="text">
<string>Populate Table</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QTableView" name="tableView"/>
</item>
</layout>
</widget>
</widget>
<resources/>
<connections/>
</ui>
test.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys, os
from PyQt5 import uic, QtWidgets
from PyQt5.QtGui import QStandardItemModel
from PyQt5.QtWidgets import QDialog, QComboBox, QApplication
class GUI(QDialog):
def __init__(self):
super(GUI, self).__init__()
dirname = os.path.dirname(os.path.abspath(__file__))
uic.loadUi(os.path.join(dirname,'main.ui'), self)
# button
self.btnPopulate.clicked.connect(self.populate)
# table model
self.header = ['col1', 'col2', 'col3']
self.QSModel = QStandardItemModel()
self.QSModel.setColumnCount(3)
self.QSModel.setHorizontalHeaderLabels(self.header)
self.tableView.setModel(self.QSModel)
# combobox delegate
self.cbDelegate = QComboBox()
self.cbDelegate.addItems(['choice1', 'choice2'])
def populate(self):
row = self.QSModel.rowCount()
for x in range(0, 7):
self.QSModel.insertRow(row)
self.QSModel.setData(self.QSModel.index(row, 0), 'data')
self.QSModel.item(row, 0).setEditable(True)
self.QSModel.setData(self.QSModel.index(row, 1), 'data')
self.QSModel.item(row, 1).setEditable(True)
# add combobox delegate to even rows
if x % 2 == 0:
print('Delegate added.')
index = self.tableView.model().index(row, 1)
self.tableView.setIndexWidget(index, self.cbDelegate)
self.QSModel.setData(self.QSModel.index(row, 2), 'data')
self.QSModel.item(row, 1).setEditable(True)
if __name__ == '__main__':
app = QApplication(sys.argv)
window = GUI()
window.show()
sys.exit(app.exec_())
但是,当我单击“填充表”按钮时,仅第一行的第二个单元格显示为QComboBox。
我该如何更改代码以在第0、2、4和6行或任何此行中显示QComboBox。 (是否需要显示QComboBox取决于到达范围行中第一个单元格的值。)
我需要使用哪种方法用QComboBox选项替换单元格内容?
最佳答案
我如何更改代码以在第0行中显示QComboBox,
2、4、6或与此相关的任意行。 (无论
需要显示QComboBox取决于第一个单元格的值
在到达行中。)
这个问题使您只能看到QComboBox,这是因为您仅创建了一个QComboBox,要解决该问题,必须为要在其中建立它们的每个单元格创建一个QComboBox。
我需要使用哪种方法替换单元格内容
QComboBox选择?
您必须将适当的信号连接到模型的setData()方法,我们可以使用QModelIndex,但是这样做很危险,因为在删除,移动或插入项目时可以更改它,因此在这种情况下,最好使用QPersistentModelIndex您必须使用信号currentIndexChanged
在此示例中,我将使用QModelIndex
:
def populate(self):
row = self.QSModel.rowCount()
for x in range(7):
self.QSModel.insertRow(row)
self.QSModel.setData(self.QSModel.index(row, 0), 'data')
self.QSModel.item(row, 0).setEditable(True)
self.QSModel.setData(self.QSModel.index(row, 1), 'data')
self.QSModel.item(row, 1).setEditable(True)
# add combobox delegate to even rows
if x % 2 == 0:
index = self.tableView.model().index(row, 1)
cbDelegate = QComboBox()
pix = QPersistentModelIndex(index)
cbDelegate.currentIndexChanged[str].connect(lambda txt, pix=pix:self.tableView.model().setData(QModelIndex(pix), txt))
cbDelegate.addItems(['choice1', 'choice2'])
self.tableView.setIndexWidget(index, cbDelegate)
self.QSModel.setData(self.QSModel.index(row, 2), 'data')
self.QSModel.item(row, 1).setEditable(True)
在此示例中,我将使用
QStandartItem
:def populate(self):
row = self.QSModel.rowCount()
for x in range(7):
self.QSModel.insertRow(row)
self.QSModel.setData(self.QSModel.index(row, 0), 'data')
self.QSModel.item(row, 0).setEditable(True)
self.QSModel.setData(self.QSModel.index(row, 1), 'data')
self.QSModel.item(row, 1).setEditable(True)
if x % 2 == 0:
item = self.tableView.model().item(row, 1)
cbDelegate = QComboBox()
cbDelegate.currentIndexChanged[str].connect(item.setText)
cbDelegate.addItems(['choice1', 'choice2'])
self.tableView.setIndexWidget(item.index(), cbDelegate)
self.QSModel.setData(self.QSModel.index(row, 2), 'data')
self.QSModel.item(row, 1).setEditable(True)
执行类似操作的另一种方法是使用委托,为此,我们创建了一个从
QStyledItemDelegate
继承的类:class ComboBoxDelegate(QStyledItemDelegate):
def paint(self, painter, option, index):
if index.row()%2 == 0:
opt = QStyleOptionComboBox()
opt.rect = option.rect
opt.currentText = index.data()
QApplication.style().drawComplexControl(QStyle.CC_ComboBox, opt, painter)
QApplication.style().drawControl(QStyle.CE_ComboBoxLabel, opt, painter)
else:
QStyledItemDelegate.paint(self, painter, option, index)
def createEditor(self, parent, option, index):
if index.row()%2 == 0:
combobox = QComboBox(parent)
options = ['choice1', 'choice2']
if index.data() not in options:
combobox.addItem(index.data())
combobox.addItems(options)
return combobox
return QStyledItemDelegate.createEditor(self, parent, option, index)
def setEditorData(self, editor, index):
if isinstance(editor, QComboBox):
text = index.data()
ix = editor.findText(text)
if ix > 0:
editor.setCurrentIndex(ix)
else:
index.model().setData(index, editor.currentText())
else:
QStyledItemDelegate.setEditorData(self, editor, index)
def setModelData(self, editor, model, index):
if isinstance(editor, QComboBox):
model.setData(index, editor.currentText())
else:
QStyledItemDelegate.setModelData(self, editor, model, index)
class GUI(QDialog):
def __init__(self):
super(GUI, self).__init__()
dirname = os.path.dirname(os.path.abspath(__file__))
uic.loadUi(os.path.join(dirname,'main.ui'), self)
self.btnPopulate.clicked.connect(self.populate)
self.header = ['col1', 'col2', 'col3']
self.QSModel = QStandardItemModel()
self.QSModel.setColumnCount(3)
self.QSModel.setHorizontalHeaderLabels(self.header)
self.tableView.setModel(self.QSModel)
self.tableView.setItemDelegateForColumn(1, ComboBoxDelegate(self.tableView))
self.populate()
def populate(self):
row = self.QSModel.rowCount()
for x in range(7):
for i, value in enumerate(['data1', 'data2', 'data3']):
self.QSModel.setItem(row+x, i, QStandardItem(value))
self.QSModel.item(row+x, i).setEditable(True)
关于python - 如何使用QCombobox选择来更新QTableView单元格?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/48105026/