【问题标题】:How to create combo-box QItemDelegate如何创建组合框 QItemDelegate
【发布时间】:2016-12-18 10:34:48
【问题描述】:

我实现了以下委托,以在 QTableView 中提供一个组合框。用例是用文本等价物替换通常对用户无意义的列(键)(例如数字 id)。

下面的 sn-p 有效(也用于保存正确的值),但它存在三个问题:

  1. 它显示原始值,而不是等效文本。
  2. QTableView 中的一系列行提供所有列,但不提供具有此委托的列。
  3. 理想情况下,我希望组合框显示为这样,而无需用户单击它来找出它是一个。

注意:键可以是任何字符串(不一定是整数)。 一个典型的例子是国家(值“France”对应于键“FR”)。

class ComboDelegate(QtGui.QItemDelegate):
    """
    A delegate that places a QComboBox in every
    cell of the column to which it is being applied
    """

    def __init__(self, parent, value_data):
        "Value_data is a list of tuples: (item, label)"
        QtGui.QItemDelegate.__init__(self, parent)
        self.value_data = value_data

    @property
    def items(self):
        "The list of items for display"
        return [item[0] for item in self.value_data]

    @property
    def labels(self):
        "The list of labels for display"
        return [item[1] for item in self.value_data]

    def item(self, label):
        "Get the item from a label"
        try:
            index = self.labels.index(label)
        except ValueError:
            pass
        print("Value no:  &%s" % index)
        return self.items[index]

    def createEditor(self, parent, option, index):
        "Create the editor (called each time)"

        combo = QtGui.QComboBox(parent)
        for duplet in self.value_data:
            # the duplet is label, item
            item, label = duplet
            combo.addItem(label)

        combo.currentIndexChanged.connect(self.currentIndexChanged)
        return combo

    def setEditorData(self, editor, index):
        editor.blockSignals(True)
        editor.setCurrentIndex(index.row())
        editor.blockSignals(False)

    def setModelData(self, editor, model, index):
        "This is the data stored into the field"
        print("Current text: %s" % editor.currentText())
        model.setData(index, self.item(editor.currentText()))

    def currentIndexChanged(self):
        self.commitData.emit(self.sender())

【问题讨论】:

    标签: python qt pyside qcombobox qitemdelegate


    【解决方案1】:

    添加{your table view}.openPersistentEditor({your QModelIndex}) 这是我的解决方案:

    import sys
    from PySide import QtGui, QtCore
    
    
    class ComboBoxDelegate(QtGui.QItemDelegate):
        def __init__(self, parent=None):
            super(ComboBoxDelegate, self).__init__(parent)
            self.items = []
    
        def setItems(self, items):
            self.items = items
    
        def createEditor(self, widget, option, index):
            editor = QtGui.QComboBox(widget)
            editor.addItems(self.items)
            return editor
    
        def setEditorData(self, editor, index):
            value = index.model().data(index, QtCore.Qt.EditRole)
            if value:
                editor.setCurrentIndex(int(value))
    
        def setModelData(self, editor, model, index):
            model.setData(index, editor.currentIndex(), QtCore.Qt.EditRole)
    
        def updateEditorGeometry(self, editor, option, index):
            editor.setGeometry(option.rect)
    
        def paint(self, painter, option, index):
            text = self.items[index.row()]
            option.text = text
            QtGui.QApplication.style().drawControl(QtGui.QStyle.CE_ItemViewItem, option, painter)
    
    if __name__ == '__main__':
        app = QtGui.QApplication(sys.argv)
        column = 0
        model = QtGui.QStandardItemModel(4, 2)
        tableview = QtGui.QTableView()
        tableview.setModel(model)
        delegate = ComboBoxDelegate()
        delegate.setItems([str(x) for x in range(10)])
        tableview.setItemDelegateForColumn(column, delegate)
    
        for row in range(4):
            for col in range(2):
                index = model.index(row, col, QtCore.QModelIndex())
                value = (row + 1)*(col + 1)
                model.setData(index, value)
    
        for i in range(model.rowCount()):
            tableview.openPersistentEditor(model.index(i, column))
        tableview.show()
        sys.exit(app.exec_())
    

    放置字符串,因为我在前面的示例中使用str(),所以我向您展示另一个显示国家/地区的示例。

    import sys
    from PySide import QtGui, QtCore
    
    
    class ComboBoxDelegate(QtGui.QItemDelegate):
        def __init__(self, parent=None):
            super(ComboBoxDelegate, self).__init__(parent)
            self.items = []
    
        def setItems(self, items):
            self.items = items
    
        def createEditor(self, widget, option, index):
            editor = QtGui.QComboBox(widget)
            editor.addItems(self.items)
            return editor
    
        def setEditorData(self, editor, index):
            value = index.model().data(index, QtCore.Qt.EditRole)
            if value:
                editor.setCurrentIndex(int(value))
    
        def setModelData(self, editor, model, index):
            model.setData(index, editor.currentIndex(), QtCore.Qt.EditRole)
    
        def updateEditorGeometry(self, editor, option, index):
            editor.setGeometry(option.rect)
    
        def paint(self, painter, option, index):
            text = self.items[index.row()]
            option.text = text
            QtGui.QApplication.style().drawControl(QtGui.QStyle.CE_ItemViewItem, option, painter)
    
    if __name__ == '__main__':
        app = QtGui.QApplication(sys.argv)
        column = 0
        model = QtGui.QStandardItemModel(4, 2)
        tableview = QtGui.QTableView()
        tableview.setModel(model)
        delegate = ComboBoxDelegate()
        delegate.setItems([QtCore.QLocale.countryToString(QtCore.QLocale.Country(locale)) for locale in range(QtCore.QLocale.Afghanistan, QtCore.QLocale.Zulu+ 1 )])
        tableview.setItemDelegateForColumn(column, delegate)
    
        for row in range(4):
            for col in range(2):
                index = model.index(row, col, QtCore.QModelIndex())
                value = (row + 1)*(col + 1)
                model.setData(index, value)
    
        for i in range(model.rowCount()):
            tableview.openPersistentEditor(model.index(i, column))
        tableview.show()
        sys.exit(app.exec_())
    

    【讨论】:

    • 非常感谢:这是清晰而优雅的!我忘了提到键可以是任何字符串,而不仅仅是整数(通常是“FR”=>“France”、“IT”=>“Italy”等。
    • 再次感谢!在这种情况下,返回的值是一个整数索引,对吗?如果我希望返回的值是一个字符串(意大利的 IT 等),对您来说最好的方法是什么?
    • 我还看到您重新实现了方法 updateEditorGeometry 和绘画。对我来说有点神秘,为什么需要这样做?我很好奇真正的问题是什么以及如何解决这些问题?
    【解决方案2】:

    模型最容易解决第一个问题,即它可以在要求DisplayRole 时提供特定值的文本,并且仍然通过EditRole 提供数值。

    显示组合框有两个选项

    1. 使用委托时,覆盖paint() 方法以绘制组合框,例如通过像QComboBox 本身一样委托给当前的小部件样式

    2. 设置索引小部件,而不是委托。见QAbstractItemView::setIndexWidget()

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-06-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多