有一个QTableView()
,其中一个列中填充了QComboBox
个es。
问题是如何根据从词典中获取的数据选择QTableView()
中的组合框中的项目
我发现我应该应用self.combo.setCurrentIndex(self.combo.findText( status_str))
,但无法理解如何在status_str
中获取变量comboBox
或将代码放在应用它的位置。
另外,我无法理解双击后make comboBox
是如何出现的。如果没有双击单元格,它必须看起来像任何其他单元格。
代码示例:
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_())
答案 0 :(得分:3)
覆盖QItemDelegate.paint
不是创建委托的推荐方法。 QItemDelegate
包含createEditor
和setEditorData
等方法,您应该覆盖这些方法。这些方法由Qt适当调用。
在createEditor
中,您应该创建comboBox
并将其返回。例如:
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
在setEditorData
中,您可以在模型中查询组合框的当前索引。这将被称为例如:
def setEditorData(self, editor, index):
value = index.model().data(index, Qt.EditRole)
editor.setCurrentIndex(editor.findText(value))
请注意,在此示例中,我依靠QItemDelegate.setModelData()
的默认实现将combobox
的当前文本保存到EditRole
。如果您想要做一些更复杂的事情(例如保存combobox
索引而不是文本),您可以将数据保存/恢复到其他角色(例如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)
以上是上述代码的最小工作示例!请注意,我已使用QVariant
关闭对sip
的支持,以便模型返回本机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_())
我刚刚注意到您关于双击后自动显示comboBox
的其他问题。我有一个黑客去做我以前用过的那个。它依赖于将视图传递给委托并将以下行添加到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_())
答案 1 :(得分:0)
为了不总是在单元格中看到组合框,您需要将QAbstracItemModel
或类似的子类化,并将其设置为QTableView
的模型,以便您可以覆盖其{{1}函数,描述每列中应显示的内容。
然后,若要在点击时显示组合框,并使其正确显示所选索引,我建议您查看QStyledItemDelegate
。
最好是自己阅读并弄清楚细节,但这里有一个关于如何使用它的大致概述:
子类data()
并在该子类中将QStyledItemDelegate
作为成员。
覆盖其QComboBox
函数以返回组合框。因此,当您将此委托设置为列的项目委托时,将显示组合框以进行编辑。
子类createEditor()
并将其设置为组合框的模型。它将保存组合框的条目,并确保始终显示正确的索引,而无需搜索索引。
再次,阅读如何正确完成每个步骤,例如如何正确地子类化抽象模型。您可以在每个班级文档的“详细信息”部分找到所有信息。