Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/342.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何在QTableView中恢复QComboBox委托的索引?_Python_Qt_Model_Pyqt_Qcombobox - Fatal编程技术网

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我会尽快抽出时间提供一个完整的例子。如果我忘了,就烦我!非常感谢你。这正是我试图找到的解决办法。