首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何使用QComboBox作为QTableView的委托

如何使用QComboBox作为QTableView的委托
EN

Stack Overflow用户
提问于 2015-01-20 03:07:18
回答 2查看 7.3K关注 0票数 5

下面的代码创建一个QTableView。双击它的项目将使用委托的QComboBox设置它。

问题

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

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

如何修复自我崩溃的combobox的行为?

附注:我注意到当ComboBox被设置为可编辑并展开它的下拉菜单时,模型的data()经常被调用.自我崩溃行为很可能是由模型引发的吗?

代码语言:javascript
运行
复制
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_())
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-01-21 23:00:48

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

代码语言:javascript
运行
复制
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_())
票数 6
EN

Stack Overflow用户

发布于 2015-01-20 05:00:36

下面是用链接到QComboBoxQActionQToolButton替换QMenu的尝试。

外观和感觉与QComboBox大致相同,还有一个附加功能,即能够设置多个选中的QActions (目前不可能检查多个组合框的项)。

代码语言:javascript
运行
复制
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_())
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28037126

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档