Python 如何在QTableView中恢复QComboBox委托的索引?
有一个Python 如何在QTableView中恢复QComboBox委托的索引?,python,qt,model,pyqt,qcombobox,Python,Qt,Model,Pyqt,Qcombobox,有一个QTableView(),其中一列中填充了QComboBoxes。 问题是如何根据从字典中获取的数据在QTableView()中的组合框中选择项 我知道我应该应用self.combo.setCurrentIndex(self.combo.findText(status_str)),但我不知道如何在comboBox中获取变量status_str,或者将其放置在代码中。 此外,我无法理解如何使组合框仅在双击后显示。若并没有双击单元格,那个么它必须看起来像其他任何单元格 代码示例: data =
QTableView()
,其中一列中填充了QComboBox
es。
问题是如何根据从字典中获取的数据在QTableView()
中的组合框中选择项
我知道我应该应用self.combo.setCurrentIndex(self.combo.findText(status_str))
,但我不知道如何在comboBox
中获取变量status_str
,或者将其放置在代码中。
此外,我无法理解如何使组合框仅在双击后显示。若并没有双击单元格,那个么它必须看起来像其他任何单元格
代码示例:
data = {"first":{"status":"closed"},"second":{"status":"expired"},"third":{ "status":"cancelled"}}
class ComboDelegate(QItemDelegate):
def __init__(self, parent):
QItemDelegate.__init__(self, parent)
def paint(self, painter, option, index):
self.combo = QComboBox(self.parent())
li = []
li.append("closed")
li.append("expired")
li.append("cancelled")
li.append("waiting")
self.combo.addItems(li)
#self.combo.setCurrentIndex(self.combo.findText( status_str ))
if not self.parent().indexWidget(index):
self.parent().setIndexWidget( index, self.combo )
class TableView(QTableView):
def __init__(self, *args, **kwargs):
QTableView.__init__(self, *args, **kwargs)
self.setItemDelegateForColumn(1, ComboDelegate(self))
class MainFrame(QWidget):
def __init__(self):
QWidget.__init__(self)
table = TableView(self)
self.model = QStandardItemModel()
table.setModel(self.model)
MainWindow = QVBoxLayout()
MainWindow.addWidget(table)
self.setLayout(MainWindow)
self.fillModel()
def fillModel(self):
for i in data:
print i
name_str = i
status_str = data[i]["status"]
name = QStandardItem(name_str)
status = QStandardItem(status_str)
items = [name, status]
self.model.appendRow(items)
if __name__ == "__main__":
app = QApplication(sys.argv)
main = MainFrame()
main.show()
main.move(app.desktop().screen().rect().center() - main.rect().center())
sys.exit(app.exec_())
为了不总是在单元格中看到组合框,您需要对其进行子类化或类似操作,并将其设置为
QTableView
的模型,以便覆盖其data()
函数,该函数描述了每列中应显示的内容
然后,要使组合框在单击时显示,并使其正确显示所选索引,我建议您查看一下
最好是你自己阅读并弄清楚细节,但这里有一个关于如何使用它的大致轮廓:
QStyledItemDelegate
并且在该子类中有您的QComboBox
作为成员createEditor()
函数以返回组合框。因此,当您将此委托设置为列的项目委托时,将显示组合框以供编辑QAbstractListModel
,并将其设置为组合框的模型。它将保存组合框的条目,并确保始终显示正确的索引,而无需搜索索引再次,请阅读这些步骤是如何正确完成的,例如,如何正确地为抽象模型创建子类。您可以在每个类文档的“详细信息”部分中找到所有信息。重写
QItemDelegate。绘制不是创建委托的推荐方法QItemDelegate
有一些方法,比如createEditor
和setEditorData
,您应该替代这些方法。Qt适当地调用了这些方法
在createEditor
中,您应该创建组合框
,并返回它。例如:
def createEditor(self, parent, option, index):
editor = QComboBox(parent)
li = []
li.append("closed")
li.append("expired")
li.append("cancelled")
li.append("waiting")
editor.addItems(li)
return editor
def setEditorData(self, editor, index):
value = index.model().data(index, Qt.EditRole)
editor.setCurrentIndex(editor.findText(value))
在setEditorData
中,您可以查询模型中组合框的当前索引。这将被称为,例如:
def createEditor(self, parent, option, index):
editor = QComboBox(parent)
li = []
li.append("closed")
li.append("expired")
li.append("cancelled")
li.append("waiting")
editor.addItems(li)
return editor
def setEditorData(self, editor, index):
value = index.model().data(index, Qt.EditRole)
editor.setCurrentIndex(editor.findText(value))
请注意,在本例中,我依靠QItemDelegate.setModelData()
的默认实现将组合框的当前文本保存到EditRole
中。如果要执行更复杂的操作(例如保存组合框而不是文本),可以将数据保存/还原到其他角色(例如Qt.UserRole
)在这种情况下,您将修改在setEditorData
方法中获取角色的位置,并覆盖setModelData
,如下所示:
def setEditorData(self, editor, index):
value = index.model().data(index, Qt.UserRole)
editor.setCurrentIndex(int(value))
def setModelData(self, editor, model, index):
model.setData(index, editor.currentIndex(), Qt.UserRole)
下面是上述代码的一个最小工作示例!注意,我已经使用sip
关闭了对QVariant
的支持,以便模型返回本机Python类型
import sys
import sip
sip.setapi('QVariant', 2)
from PyQt4.QtGui import *
from PyQt4.QtCore import *
data = {"first":{"status":"closed"},"second":{"status":"expired"},"third":{ "status":"cancelled"}}
class ComboDelegate(QItemDelegate):
def createEditor(self, parent, option, index):
editor = QComboBox(parent)
li = []
li.append("closed")
li.append("expired")
li.append("cancelled")
li.append("waiting")
editor.addItems(li)
return editor
def setEditorData(self, editor, index):
value = index.model().data(index, Qt.EditRole)
editor.setCurrentIndex(editor.findText(value))
class Example(QMainWindow):
def __init__(self):
super(Example, self).__init__()
self.tableview = QTableView()
self.tableview.setItemDelegateForColumn(1, ComboDelegate())
self.setCentralWidget(self.tableview)
self.model = QStandardItemModel()
self.tableview.setModel(self.model)
self.fillModel()
self.show()
def fillModel(self):
for i in data:
name_str = i
status_str = data[i]["status"]
name = QStandardItem(name_str)
status = QStandardItem(status_str)
items = [name, status]
self.model.appendRow(items)
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
编辑
我刚刚注意到您关于双击后自动显示组合框的另一个问题。我有一种我以前用过的技巧。它依赖于将视图传递给代理,并将以下行添加到createEditor
方法:
editor.activated.connect(lambda index, editor=editor: self._view.commitData(editor))
editor.activated.connect(lambda index, editor=editor: self._view.closeEditor(editor,QAbstractItemDelegate.NoHint))
QTimer.singleShot(10,editor.showPopup)
完整工作示例:
import sys
import sip
sip.setapi('QVariant', 2)
from PyQt4.QtGui import *
from PyQt4.QtCore import *
data = {"first":{"status":"closed"},"second":{"status":"expired"},"third":{ "status":"cancelled"}}
class ComboDelegate(QItemDelegate):
def __init__(self, view):
QItemDelegate.__init__(self)
self._view = view
def createEditor(self, parent, option, index):
editor = QComboBox(parent)
li = []
li.append("closed")
li.append("expired")
li.append("cancelled")
li.append("waiting")
editor.addItems(li)
editor.activated.connect(lambda index, editor=editor: self._view.commitData(editor))
editor.activated.connect(lambda index, editor=editor: self._view.closeEditor(editor,QAbstractItemDelegate.NoHint))
QTimer.singleShot(10,editor.showPopup)
return editor
def setEditorData(self, editor, index):
value = index.model().data(index, Qt.EditRole)
editor.setCurrentIndex(editor.findText(value))
class Example(QMainWindow):
def __init__(self):
super(Example, self).__init__()
self.tableview = QTableView()
self.tableview.setItemDelegateForColumn(1, ComboDelegate(self.tableview))
self.setCentralWidget(self.tableview)
self.model = QStandardItemModel()
self.tableview.setModel(self.model)
self.fillModel()
self.show()
def fillModel(self):
for i in data:
name_str = i
status_str = data[i]["status"]
name = QStandardItem(name_str)
status = QStandardItem(status_str)
items = [name, status]
self.model.appendRow(items)
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
如果他们已经在使用QStandardItemModel
,则无需将其子类化。您可以使用item.setData(data,role)
。@三个菠萝,所以我尝试了status=QStandardItem()status.setData(status\u str,Qt.EditRole)
它显示组合框,status列中的每个单元格都有相同的选择状态,不管status\u str
的值是什么。你能举例说明我该怎么做吗。我确实阅读过文档,但由于缺乏经验,我无法在没有文档的情况下将简单的信息绑定在一起examples@SergiiArtele我会尽快抽出时间提供一个完整的例子。如果我忘了,就烦我!非常感谢你。这正是我试图找到的解决办法。