Checkboxes in a Combobox using PyQt

纵然是瞬间 提交于 2019-11-28 01:02:29

问题


I need to implement a drop down list that contains CheckBoxes, much like having the entries in a ComboBox being CheckBoxes. But QComboBox doesn't accept QCheckBox as its member and I couldn't find any alternate solution. I found an implementation in C++ on the Qt Wiki, but don't know how to port it to python.


回答1:


When i needed this, I come up with an easier solution (at least it is not necessary to subclass QCombobox). It worked for me. That is create a menu with checkable actions and set it to a button. Then connect either the menu or the actions to a slot.

The code in Qt(haven't use PyQt yet, sorry, i hope you can port that one, seems easier to me) was something like that:

QMenu *menu = new QMenu;
QAction *Act1 = new QAction("Action 1", menu);
Act1->setCheckable(true);
QAction *Act2 = new QAction("Action 2", menu);
Act2->setCheckable(true);
menu->addAction(Act1);
menu->addAction(Act2);

QPushButton *btn = new QPushButton("Btn");    
btn->setMenu(menu);

Hope this helps




回答2:


Use the Combobox item model, since items support checkBoxes you just need to mark the item to be checkable by the user, and set an initial checkState to make the checkBox appear (it does only show if there is a valid state)

item.setFlags(QtCore.Qt.ItemIsUserCheckable | QtCore.Qt.ItemIsEnabled)
item.setCheckState(QtCore.Qt.Unchecked)  # causes checkBox to show

Here is a minimal subclass example:

from PyQt5 import QtGui, QtCore, QtWidgets
import sys, os

# subclass
class CheckableComboBox(QtWidgets.QComboBox):
    # once there is a checkState set, it is rendered
    # here we assume default Unchecked
    def addItem(self, item):
        super(CheckableComboBox, self).addItem(item)
        item = self.model().item(self.count()-1,0)
        item.setFlags(QtCore.Qt.ItemIsUserCheckable | QtCore.Qt.ItemIsEnabled)
        item.setCheckState(QtCore.Qt.Unchecked)

    def itemChecked(self, index):
        item = self.model().item(i,0)
        return item.checkState() == QtCore.Qt.Checked

# the basic main()
app = QtWidgets.QApplication(sys.argv)
dialog = QtWidgets.QMainWindow()
mainWidget = QtWidgets.QWidget()
dialog.setCentralWidget(mainWidget)
ComboBox = CheckableComboBox(mainWidget)
for i in range(6):
    ComboBox.addItem("Combobox Item " + str(i))

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



回答3:


I have replied a similar question at How do I create a tree view (with checkbox) inside a combo box - PyQt, but anyway and for completeness in the reply i paste you here:

You should create a model that support Qt.CheckStateRole in data and SetData methods and the flag Qt.ItemIsUserCheckable in the flags method.

I Paste you here an example i am using in a project, this is a QSortFilterProxyModel generic implementation to use in any model but you can use the same ideas in your model implementation, obviously i am using internal structures in this subclass you have not directly in PyQt and are attached to my internal implementation (self.booleanSet and self.readOnlySet).

def flags(self, index):
    if not index.isValid():
        return Qt.ItemIsEnabled

    if index.column() in self.booleanSet:
        return Qt.ItemIsUserCheckable | Qt.ItemIsSelectable | Qt.ItemIsEnabled
    elif index.column() in self.readOnlySet:
        return Qt.ItemIsSelectable | Qt.ItemIsEnabled
    else:
        return QSortFilterProxyModel.flags(self, index)

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

    if index.column() in self.booleanSet and role in (Qt.CheckStateRole, Qt.DisplayRole):
        if role == Qt.CheckStateRole:
            value = QVariant(Qt.Checked) if index.data(Qt.EditRole).toBool() else QVariant(Qt.Unchecked)
            return value
        else: #if role == Qt.DisplayRole:
            return QVariant()
    else:
        return QSortFilterProxyModel.data(self, index, role)

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

    if index.column() in self.booleanSet and role == Qt.CheckStateRole:
        value = QVariant(True) if data.toInt()[0] == Qt.Checked else QVariant(False)
        return QSortFilterProxyModel.setData(self, index, value, Qt.EditRole)
    else:
        return QSortFilterProxyModel.setData(self, index, data, role)


来源:https://stackoverflow.com/questions/5226091/checkboxes-in-a-combobox-using-pyqt

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!