PyQt: How to set Combobox Items be Checkable?

This idea of a multi-select combo has come up before, but I’m not sure that its the best solution. Really, all that’s needed is a tool-button with a drop-down menu (similar to the history buttons in a web-browser).

Here’s a basic demo that illustrates both options (button left, combo right):

screenshot screenshot

PyQt5:

from PyQt5 import QtWidgets, QtGui, QtCore

class CheckableComboBox(QtWidgets.QComboBox):
    def __init__(self):
        super(CheckableComboBox, self).__init__()
        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)

class Dialog_01(QtWidgets.QMainWindow):
    def __init__(self):
        super().__init__()
        myQWidget = QtWidgets.QWidget()
        myBoxLayout = QtWidgets.QHBoxLayout()
        myQWidget.setLayout(myBoxLayout)
        self.setCentralWidget(myQWidget)
        self.ComboBox = CheckableComboBox()
        self.toolbutton = QtWidgets.QToolButton(self)
        self.toolbutton.setText('Categories ')
        self.toolmenu = QtWidgets.QMenu(self)
        for i in range(3):
            self.ComboBox.addItem('Category %s' % i)
            item = self.ComboBox.model().item(i, 0)
            item.setCheckState(QtCore.Qt.Unchecked)
            action = self.toolmenu.addAction('Category %s' % i)
            action.setCheckable(True)
        self.toolbutton.setMenu(self.toolmenu)
        self.toolbutton.setPopupMode(QtWidgets.QToolButton.InstantPopup)
        myBoxLayout.addWidget(self.toolbutton)
        myBoxLayout.addWidget(self.ComboBox)

if __name__ == '__main__':

    app = QtWidgets.QApplication(['Test'])
    dialog_1 = Dialog_01()
    dialog_1.show()
    app.exec_()
    
**PyQt4**:

from PyQt4 import QtGui, QtCore

class CheckableComboBox(QtGui.QComboBox):
    def __init__(self):
        super(CheckableComboBox, self).__init__()
        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)

class Dialog_01(QtGui.QMainWindow):
    def __init__(self):
        super(QtGui.QMainWindow, self).__init__()
        myQWidget = QtGui.QWidget()
        myBoxLayout = QtGui.QHBoxLayout()
        myQWidget.setLayout(myBoxLayout)
        self.setCentralWidget(myQWidget)
        self.ComboBox = CheckableComboBox()
        self.toolbutton = QtGui.QToolButton(self)
        self.toolbutton.setText('Categories ')
        self.toolmenu = QtGui.QMenu(self)
        self.toolbutton.setMenu(self.toolmenu)
        self.toolbutton.setPopupMode(QtGui.QToolButton.InstantPopup)
        for i in range(3):
            self.ComboBox.addItem('Category %s' % i)
            item = self.ComboBox.model().item(i, 0)
            item.setCheckState(QtCore.Qt.Unchecked)
            action = self.toolmenu.addAction('Category %s' % i)
            action.setCheckable(True)
        myBoxLayout.addWidget(self.toolbutton)
        myBoxLayout.addWidget(self.ComboBox)

if __name__ == '__main__':

    app = QtGui.QApplication(['Test'])
    dialog_1 = Dialog_01()
    dialog_1.show()
    app.exec_()

Leave a Comment