在PyQt中使用带复选框的下拉框
我想做一个下拉列表,里面有复选框,类似于把ComboBox里的选项变成复选框。但是QComboBox不支持把QCheckBox作为它的成员,我找不到其他的解决办法。我在Qt Wiki上找到了一种用C++实现的方法,但我不知道怎么把它转换成Python代码。
3 个回答
2
我之前在这个链接上回答过一个类似的问题:如何在组合框中创建一个带复选框的树视图 - PyQt。不过为了完整起见,我在这里再给你贴一下:
你需要创建一个模型,这个模型要支持 Qt.CheckStateRole 这个功能,在数据和设置数据的方法中都要用到,同时在标志方法中要使用 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)
8
使用组合框的项目模型,因为这些项目支持复选框。你只需要标记哪些项目可以被用户勾选,并设置一个初始的勾选状态,这样复选框就会显示出来(只有在有有效状态时,复选框才会出现)。
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_())
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);
希望这对你有帮助