繁体   English   中英

如何使用QComboBox作为QTableView的委托

[英]How to use QComboBox as delegate with QTableView

下面的代码创建了一个QTableView 双击其项目将使用委派的QComboBox

问题
单击ComboBox时,其下拉菜单会显示瞬间,然后折叠回其展开状态。

在此输入图像描述

如果使用combox.setEditable(True)comboBox设置为可编辑,则下拉菜单将根据需要保持打开状态。 但随后combobox的项目变得可编辑。 并不是所需要的。 因为combobox的项目只能选择。

如何解决自我崩溃的combobox的行为?

Ps我注意到当ComboBox被设置为可编辑并且其下拉菜单被展开时,模型的data()被不断调用...是否可能由模型触发自崩溃行为?

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_())

您的原始代码在PyQt5中工作, combobox保持打开状态。 但是用户必须单击以打开编辑器,然后单击以打开combobox 为了避免这种情况,我在代码中用QlistWidget替换了QComboBox 另外我设置了editorGeometry

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_())

以下是尝试用QToolButton替换QComboBox ,链接到QMenuQAction

外观与QComboBox大致相同,还具有能够设置多个QActions (目前无法检查多个组合框的项目)。

在此输入图像描述

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_())

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM