这种多选组合的想法 以前就出现过 ,但我不确定它是否是最好的解决方案。实际上,所需要的只是一个带有下拉菜单的工具按钮(类似于 Web 浏览器中的历史记录按钮)。
下面是一个基本演示,说明了这两个选项(左边的按钮,右边的组合):
PyQt5 的安装方法 :
from PyQt5 import QtCore, QtGui, QtWidgets
class CheckableComboBox(QtWidgets.QComboBox):
def __init__(self, title = '', parent=None):
super().__init__(parent)
self.setTitle(title)
self.view().pressed.connect(self.handleItemPressed)
self.setModel(QtGui.QStandardItemModel(self))
def handleItemPressed(self, index):
item = self.model().itemFromIndex(index)
if item.checkState() == QtCore.Qt.Checked:
item.setCheckState(QtCore.Qt.Unchecked)
else:
item.setCheckState(QtCore.Qt.Checked)
def title(self):
return self._title
def setTitle(self, title):
self._title = title
self.repaint()
def paintEvent(self, event):
painter = QtWidgets.QStylePainter(self)
painter.setPen(self.palette().color(QtGui.QPalette.Text))
opt = QtWidgets.QStyleOptionComboBox()
self.initStyleOption(opt)
opt.currentText = self._title
painter.drawComplexControl(QtWidgets.QStyle.CC_ComboBox, opt)
painter.drawControl(QtWidgets.QStyle.CE_ComboBoxLabel, opt)
class Dialog(QtWidgets.QWidget):
def __init__(self):
super().__init__()
hbox = QtWidgets.QHBoxLayout()
self.comboBox = CheckableComboBox('Categories', self)
self.toolButton = QtWidgets.QToolButton(self)
self.toolButton.setText('Categories ')
self.toolMenu = QtWidgets.QMenu(self)
for index in range(3):
self.comboBox.addItem(f'Category {index}')
item = self.comboBox.model().item(index, 0)
item.setCheckState(QtCore.Qt.Unchecked)
action = self.toolMenu.addAction(f'Category {index}')
action.setCheckable(True)
self.toolButton.setMenu(self.toolMenu)
self.toolButton.setPopupMode(QtWidgets.QToolButton.InstantPopup)
hbox.addWidget(self.toolButton)
hbox.addWidget(self.comboBox)
layout = QtWidgets.QVBoxLayout(self)
layout.addLayout(hbox)
layout.addStretch()
if __name__ == '__main__':
app = QtWidgets.QApplication(['Test'])
dialog = Dialog()
dialog.show()
app.exec()
PyQt4 :
from PyQt4 import QtCore, QtGui
class CheckableComboBox(QtGui.QComboBox):
def __init__(self, title = '', parent=None):
super().__init__(parent)
self.setTitle(title)
self.view().pressed.connect(self.handleItemPressed)
self.setModel(QtGui.QStandardItemModel(self))
def handleItemPressed(self, index):
item = self.model().itemFromIndex(index)
if item.checkState() == QtCore.Qt.Checked:
item.setCheckState(QtCore.Qt.Unchecked)
else:
item.setCheckState(QtCore.Qt.Checked)
def title(self):
return self._title
def setTitle(self, title):
self._title = title
self.repaint()
def paintEvent(self, event):
painter = QtGui.QStylePainter(self)
painter.setPen(self.palette().color(QtGui.QPalette.Text))
opt = QtGui.QStyleOptionComboBox()
self.initStyleOption(opt)
opt.currentText = self._title
painter.drawComplexControl(QtGui.QStyle.CC_ComboBox, opt)
painter.drawControl(QtGui.QStyle.CE_ComboBoxLabel, opt)
class Dialog(QtGui.QWidget):
def __init__(self):
super().__init__()
hbox = QtGui.QHBoxLayout()
self.comboBox = CheckableComboBox('Categories', self)
self.toolButton = QtGui.QToolButton(self)
self.toolButton.setText('Categories ')
self.toolMenu = QtGui.QMenu(self)
for index in range(3):
self.comboBox.addItem('Category %s' % index)
item = self.comboBox.model().item(index, 0)
item.setCheckState(QtCore.Qt.Unchecked)
action = self.toolMenu.addAction('Category %s' % index)
action.setCheckable(True)
self.toolButton.setMenu(self.toolMenu)
self.toolButton.setPopupMode(QtGui.QToolButton.InstantPopup)
hbox.addWidget(self.toolButton)
hbox.addWidget(self.comboBox)
layout = QtGui.QVBoxLayout(self)
layout.addLayout(hbox)
layout.addStretch()
if __name__ == '__main__':
app = QtGui.QApplication(['Test'])
dialog = Dialog()
dialog.show()
app.exec()