Python 如何将QComboBox用作QTableView的委托

Python 如何将QComboBox用作QTableView的委托,python,qt,pyqt,qtableview,qcombobox,Python,Qt,Pyqt,Qtableview,Qcombobox,下面的代码创建一个QTableView。双击其项目将使用委派的QComboBox对其进行设置 问题: 单击组合框时,其下拉菜单会立即显示,然后折叠回展开状态 如果使用combox.setEditable(True)将组合框设置为可编辑, 下拉菜单将根据需要保持打开状态。但是,组合框的项目将变得可编辑。这不是我们所需要的。由于组合框的项目只能选择 如何修复自折叠组合框的行为 另外,我注意到当组合框设置为可编辑且其下拉菜单展开时,模型的数据()不断被调用。。。模型是否可能触发自崩溃行为 impor

下面的代码创建一个
QTableView
。双击其项目将使用委派的
QComboBox
对其进行设置

问题
单击组合框时,其下拉菜单会立即显示,然后折叠回展开状态

如果使用
combox.setEditable(True)
将组合框设置为可编辑, 下拉菜单将根据需要保持打开状态。但是,
组合框
的项目将变得可编辑。这不是我们所需要的。由于
组合框
的项目只能选择

如何修复自折叠组合框的行为

另外,我注意到当
组合框
设置为可编辑且其下拉菜单展开时,模型的
数据()
不断被调用。。。模型是否可能触发自崩溃行为

import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *

class ComboDelegate(QItemDelegate):
    comboItems=['Combo_Zero', 'Combo_One','Combo_Two']
    def createEditor(self, parent, option, proxyModelIndex):
        combo = QComboBox(parent)
        combo.addItems(self.comboItems)
        # combo.setEditable(True)
        self.connect(combo, SIGNAL("currentIndexChanged(int)"), self, SLOT("currentIndexChanged()"))
        return combo

    def setModelData(self, combo, model, index):
        comboIndex=combo.currentIndex()
        text=self.comboItems[comboIndex]        
        model.setData(index, text)
        print '\t\t\t ...setModelData() 1', text

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

class MyModel(QAbstractTableModel):
    def __init__(self, parent=None, *args):
        QAbstractTableModel.__init__(self, parent, *args)
        self.items=['Data_Item01','Data_Item02','Data_Item03']

    def rowCount(self, parent=QModelIndex()):
        return len(self.items)
    def columnCount(self, parent=QModelIndex()):
        return 1

    def data(self, index, role):        
        if not index.isValid(): return QVariant()

        row=index.row()
        item=self.items[row]

        if row>len(self.items): return QVariant()

        if role == Qt.DisplayRole:
            print ' << >> MyModel.data() returning ...', item
            return QVariant(item) 

    def flags(self, index):
        return Qt.ItemIsEditable | Qt.ItemIsEnabled

    def setData(self, index, text):
        self.items[index.row()]=text

if __name__ == '__main__':
    app = QApplication(sys.argv)

    model = MyModel()
    tableView = QTableView()
    tableView.setModel(model)

    delegate = ComboDelegate()

    tableView.setItemDelegate(delegate)
    tableView.resizeRowsToContents()

    tableView.show()
    sys.exit(app.exec_())
导入系统 从PyQt4.QtCore导入* 从PyQt4.QtGui导入* 类组合委托(QItemDelegate): comboItems=['Combo\u Zero'、'Combo\u One'、'Combo\u Two'] def createEditor(自、父、选项、proxyModelIndex): 组合=QComboBox(父项) combo.addItems(self.comboItems) #combo.setEditable(真) self.connect(组合,信号(“currentIndexChanged(int)”),self,插槽(“currentIndexChanged()”) 返回组合 def setModelData(自身、组合、模型、索引): comboIndex=combo.currentIndex() text=self.comboItems[comboIndex] model.setData(索引、文本) 打印“\t\t\t…setModelData()1”,文本 @pyqtSlot() def currentIndexChanged(自): self.commitData.emit(self.sender()) 类MyModel(QAbstractTableModel): 定义初始化(self,parent=None,*args): QAbstractTableModel.\uuuuu init\uuuuu(self,parent,*args) self.items=['Data\u Item01','Data\u Item02','Data\u Item03'] def行数(self,parent=QModelIndex()): 返回len(自我项目) def columnCount(self,parent=QModelIndex()): 返回1 def数据(自身、索引、角色): 如果不是index.isValid():返回QVariant() 行=索引。行() 项目=自身。项目[行] 如果行>len(self.items):返回QVariant() 如果角色==Qt.DisplayRole: print'>MyModel.data()返回…',项 返回QVariant(项目) def标志(自、索引): 返回Qt.ItemIsEditable | Qt.ItemIsEnabled def setData(自身、索引、文本): self.items[index.row()]=文本 如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu': app=QApplication(sys.argv) model=MyModel() tableView=QTableView() tableView.setModel(模型) delegate=ComboDelegate() tableView.setItemDelegate(委托) tableView.resizeRowsToContents() tableView.show() sys.exit(app.exec_())
这里尝试用链接到
QMenu
QAction
s的
QToolButton
替换
QComboBox

该外观与
QComboBox
大致相同,另外一个功能是能够设置多个
QActions
选中(目前不可能选中多个组合框的项目)

导入系统 从PyQt4.QtCore导入* 从PyQt4.QtGui导入* 类组合委托(QItemDelegate): comboItems=['Combo\u Zero'、'Combo\u One'、'Combo\u Two'] 定义初始化(自身,父级): QItemDelegate.\uuuu init\uuuuu(self,parent=None) self.actionEmissed=None def createEditor(自身、父项、选项、索引): 如果不是index.isValid():返回 model=index.model() itemName=model.data(索引,Qt.DisplayRole) toolButton=QToolButton(父级) toolButton.setText(itemName.toString()) toolButton.setPopupMode(QToolButton.InstantPopup) 菜单=QMenu(父菜单) action1=QAction('action01',菜单,可检查=True) action2=QAction('Action 02',菜单,可检查=True) action3=QAction('Action 03',菜单,可检查=True) action1.setObjectName('Action 01') action2.setObjectName('Action 02') action3.setObjectName('Action 03') action1.setChecked(True) 操作3.setChecked(真) 连接(action1,信号(“触发(bool)”),self,插槽(“actionTriggered()”) 连接(action2,信号(“触发(bool)”),self,插槽(“actionTriggered()”) 连接(action3,信号(“触发(bool)”),self,插槽(“actionTriggered()”) 菜单.添加操作(操作1) 菜单.添加操作(操作2) 菜单.添加操作(操作3) 工具按钮。设置菜单(菜单) 返回工具按钮 def setModelData(自身、工具按钮、模型、索引): 打印“\t\t\t…setModelData()1”,工具按钮,模型,索引 如果不是self.actionemissed:返回 menu=toolButton.menu() 对于菜单中的操作。操作(): actionName=action.objectName() actionStatus=action.isChecked() 如果操作状态: model.setData(索引、actionName) 打印“#####”,操作名称,操作状态 @pyqtSlot() def动作触发(自): self.actionEmissed=self.sender() self.commitData.emit(self.actionEmitted) 打印“actionTriggered…”,self.actionEmissed 类MyModel(QAbstractTableModel): 定义初始化(self,parent=None,*args): QAbstractTableModel.\uuuuu init\uuuuu(self,parent,*args) self.items=['Data\u Item01','Data\u Item02','Data\u Item03'] def行数(self,parent=QModelIndex()): 返回len(自我项目) def columnCount(self,parent=QModelIndex()): 返回1 def数据(自身、索引、角色): 如果不是index.isValid():返回QVariant() 行=索引。行() 项目=自身。项目[行] 如果行>len(self.items):返回QVariant() 如果角色==Qt.DisplayRole: print'>MyModel.data()返回
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *

class ComboDelegate(QItemDelegate):
    comboItems=['Combo_Zero', 'Combo_One','Combo_Two']
    def __init__(self, parent):
        QItemDelegate.__init__(self, parent=None)
        self.actionEmitted=None

    def createEditor(self, parent, option, index):
        if not index.isValid(): return

        model=index.model()
        itemName=model.data(index, Qt.DisplayRole)

        toolButton=QToolButton(parent)
        toolButton.setText( itemName.toString() )

        toolButton.setPopupMode(QToolButton.InstantPopup)        

        menu=QMenu(parent)

        action1=QAction('Action 01', menu, checkable=True)
        action2=QAction('Action 02', menu, checkable=True)
        action3=QAction('Action 03', menu, checkable=True)

        action1.setObjectName('Action 01')
        action2.setObjectName('Action 02')
        action3.setObjectName('Action 03')       

        action1.setChecked(True)
        action3.setChecked(True)

        self.connect(action1, SIGNAL("triggered(bool)"), self, SLOT("actionTriggered()"))
        self.connect(action2, SIGNAL("triggered(bool)"), self, SLOT("actionTriggered()"))
        self.connect(action3, SIGNAL("triggered(bool)"), self, SLOT("actionTriggered()"))

        menu.addAction(action1)
        menu.addAction(action2)
        menu.addAction(action3)

        toolButton.setMenu(menu) 

        return toolButton

    def setModelData(self, toolButton, model, index):
        print '\t\t\t ...setModelData() 1', toolButton, model, index

        if not self.actionEmitted: return

        menu=toolButton.menu()
        for action in menu.actions():
            actionName=action.objectName()
            actionStatus=action.isChecked()            
            if actionStatus:
                model.setData(index, actionName)
                print '####', actionName, actionStatus

    @pyqtSlot()
    def actionTriggered(self): 
        self.actionEmitted=self.sender()        
        self.commitData.emit( self.actionEmitted )
        print 'actionTriggered.....', self.actionEmitted


class MyModel(QAbstractTableModel):
    def __init__(self, parent=None, *args):
        QAbstractTableModel.__init__(self, parent, *args)
        self.items=['Data_Item01','Data_Item02','Data_Item03']

    def rowCount(self, parent=QModelIndex()):
        return len(self.items)
    def columnCount(self, parent=QModelIndex()):
        return 1

    def data(self, index, role):        
        if not index.isValid(): return QVariant()

        row=index.row()
        item=self.items[row]

        if row>len(self.items): return QVariant()

        if role == Qt.DisplayRole:
            print ' << >> MyModel.data() returning ...', item
            return QVariant(item) 

    def flags(self, index):
        return Qt.ItemIsEditable | Qt.ItemIsEnabled

    def setData(self, index, itemName):
        self.items[index.row()]=itemName

if __name__ == '__main__':
    app = QApplication(sys.argv)

    combo=QComboBox()
    combo.addItems(['Combo_Zero', 'Combo_One','Combo_Two'])

    model = MyModel()
    tableView = QTableView()
    tableView.setModel(model)

    delegate = ComboDelegate(tableView)

    tableView.setItemDelegate(delegate)
    tableView.resizeRowsToContents()

    tableView.show()
    sys.exit(app.exec_())
import sys
# from PyQt4.QtCore import *
# from PyQt4.QtGui import *

from PyQt5.QtCore import *
from PyQt5.QtWidgets import *

class ComboDelegate(QItemDelegate):
    editorItems=['Combo_Zero', 'Combo_One','Combo_Two']
    height = 25
    width = 200
    def createEditor(self, parent, option, index):
        editor = QListWidget(parent)
        # editor.addItems(self.editorItems)
        # editor.setEditable(True)
        editor.currentItemChanged.connect(self.currentItemChanged)
        return editor

    def setEditorData(self,editor,index):
        z = 0
        for item in self.editorItems:
            ai = QListWidgetItem(item)
            editor.addItem(ai)
            if item == index.data():
                editor.setCurrentItem(editor.item(z))
            z += 1
        editor.setGeometry(0,index.row()*self.height,self.width,self.height*len(self.editorItems))

    def setModelData(self, editor, model, index):
        editorIndex=editor.currentIndex()
        text=editor.currentItem().text() 
        model.setData(index, text)
        # print '\t\t\t ...setModelData() 1', text

    @pyqtSlot()
    def currentItemChanged(self): 
        self.commitData.emit(self.sender())

class MyModel(QAbstractTableModel):
    def __init__(self, parent=None, *args):
        QAbstractTableModel.__init__(self, parent, *args)
        self.items=['Data_Item01','Data_Item02','Data_Item03']

    def rowCount(self, parent=QModelIndex()):
        return len(self.items)
    def columnCount(self, parent=QModelIndex()):
        return 1

    def data(self, index, role):        
        if not index.isValid(): return QVariant()

        row=index.row()
        item=self.items[row]

        if row>len(self.items): return QVariant()

        if role == Qt.DisplayRole:
            # print ' << >> MyModel.data() returning ...', item
            return QVariant(item) 

    def flags(self, index):
        return Qt.ItemIsEditable | Qt.ItemIsEnabled

    def setData(self, index, text):
        self.items[index.row()]=text

if __name__ == '__main__':
    app = QApplication(sys.argv)

    model = MyModel()
    tableView = QTableView()
    tableView.setModel(model)

    delegate = ComboDelegate()

    tableView.setItemDelegate(delegate)
    for i in range(0,tableView.model().rowCount()):
        tableView.setRowHeight(i,tableView.itemDelegate().height)
    for i in range(0,tableView.model().columnCount()):
        tableView.setColumnWidth(i,tableView.itemDelegate().width)

    tableView.show()
    sys.exit(app.exec_())