使用PyQt在组合框中添加复选框

8

我需要实现一个下拉列表,其中包含复选框,就像在ComboBox中的条目是复选框一样。但是QComboBox不接受QCheckBox作为其成员,我找不到任何替代方案。我在Qt Wiki上找到了一个C++实现,但不知道如何将其移植到Python。

3个回答

9

当我需要这个功能时,我想出了一种更简单的解决方法(至少不需要子类化QCombobox)。这对我有用。

具体方法是创建一个菜单,其中有可勾选的操作,并将其设置为一个按钮。然后将菜单或操作连接到槽函数。

在Qt中的代码(我还没有使用过PyQt,抱歉,希望你能移植它,对我来说似乎更容易)大致如下:

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);

希望这能帮到您。

谢谢,这是一个有用的答案,帮我省了很多工作。 - PeerPandit

8
使用Combobox项模型,因为它支持复选框。只需要将要检查的项目标记为可由用户检查,并设置初始checkState以使复选框出现(仅当存在有效状态时才显示)。
item.setFlags(QtCore.Qt.ItemIsUserCheckable | QtCore.Qt.ItemIsEnabled)
item.setCheckState(QtCore.Qt.Unchecked)  # causes checkBox to show

以下是一个最小子类示例:

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

在这种情况下,如何更新显示的值?用户选择了几个选项(复选框),但CheckableComboBox仅从列表中显示值。 - constructor
需要将“i”更改为“index”在itemChecked中。 - constructor

2
我曾在 如何在PyQt中创建带复选框的树形视图组合框 中回答过类似的问题,但为了完整起见,在这里我还是会粘贴一下我的回答:
你需要创建一个支持 Qt.CheckStateRole 的数据和 SetData 方法,并在 flags 方法中添加 Qt.ItemIsUserCheckable 标志的模型。
我在项目中使用的示例代码如下,这是一个 QSortFilterProxyModel 的通用实现,可用于任何模型,但您可以在自己的模型实现中使用相同的思路。显然,我在这个子类中使用了内部结构,您没有直接在 PyQt 中使用,它们与我的内部实现(self.booleanSet 和 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)

1
我个人认为,如果有人能够发布一个最小工作示例,那将非常有帮助。 - eric

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接