PyQt: How to set Combobox Items be Checkable?
Solution 1
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 an update of the example that illustrates both options:
from PyQt4 import QtGui, QtCore
import sys, os
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.QVBoxLayout()
myQWidget.setLayout(myBoxLayout)
self.setCentralWidget(myQWidget)
self.ComboBox = CheckableComboBox()
for i in range(3):
self.ComboBox.addItem("Combobox Item " + str(i))
item = self.ComboBox.model().item(i, 0)
item.setCheckState(QtCore.Qt.Unchecked)
self.toolbutton = QtGui.QToolButton(self)
self.toolbutton.setText('Select Categories ')
self.toolmenu = QtGui.QMenu(self)
for i in range(3):
action = self.toolmenu.addAction("Category " + str(i))
action.setCheckable(True)
self.toolbutton.setMenu(self.toolmenu)
self.toolbutton.setPopupMode(QtGui.QToolButton.InstantPopup)
myBoxLayout.addWidget(self.toolbutton)
myBoxLayout.addWidget(self.ComboBox)
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
dialog_1 = Dialog_01()
dialog_1.show()
dialog_1.resize(480,320)
sys.exit(app.exec_())
Solution 2
It is very easy. Just set the item Checkable using the flags() function in the model associated with the comboBox.
def flags(self, index):
return Qt.ItemIsUserCheckable | Qt.ItemIsSelectable | Qt.ItemIsEnabled
UPDATE
This may not be the best method, But it should sort your problem. Here is a something u may want look at , IF you have space restrictionn and cannot display the complete listView, Just resize it until it looks like a ComboBox.
alphanumeric
Updated on June 08, 2022Comments
-
alphanumeric almost 2 years
To keep the GUI widgets number to minimum I need to find a way to give to user a choice of pull-down menu items that could be used to filter out the displayed in a listWidget items. Let's say the listWidget lists 5 different categories of Items: "Cat A", "Cat B","Cat C","Cat D","Cat E". I could implement the radio or checkboxes for each item category. But then 5 radio buttons or checkboxes would take a lot of GUI space. A combobox with the checkable items seems to be a right choice. Any ideas?
from PyQt4 import QtGui, QtCore import sys, os class CheckableComboBox(QtGui.QComboBox): def __init__(self): super(CheckableComboBox, self).__init__() def flags(self, index): return Qt.ItemIsUserCheckable | Qt.ItemIsSelectable | Qt.ItemIsEnabled class Dialog_01(QtGui.QMainWindow): def __init__(self): super(QtGui.QMainWindow,self).__init__() myQWidget = QtGui.QWidget() myBoxLayout = QtGui.QVBoxLayout() myQWidget.setLayout(myBoxLayout) self.setCentralWidget(myQWidget) self.ComboBox = CheckableComboBox() for i in range(3): self.ComboBox.addItem("Combobox Item " + str(i)) myBoxLayout.addWidget(self.ComboBox) if __name__ == '__main__': app = QtGui.QApplication(sys.argv) dialog_1 = Dialog_01() dialog_1.show() dialog_1.resize(480,320) sys.exit(app.exec_())
-
alphanumeric about 10 yearsJust added it to the code. Thanks! I can't find a way to set multiple combobox items checked. Is it possible? I need multiple items to be checked at the same time...
-
thecreator232 about 10 yearsi think that may not be possible because a combobox is used to select 1 option out of the list. I am not sure about it , i'll have to check it out.
-
thecreator232 about 10 years@Sputnix : If you wish to check multiple options then ListView will be a better option.
-
alphanumeric about 10 yearsThis looks very the same as I've envisioned it. Thanks Ekhumoro!
-
alphanumeric about 10 yearsIf I use self.connect(action, QtCore.SIGNAL("triggered()"), self.myMethod) there are no args sent. It would make sense to submit a toolmenu's action as an arg to myMethod(self, arg). Would you mind showing how each action could be hooked to a method that would be used to receive an action as an arg (so an action's "checked" status could be verified (along with its name)? ("action" here is one of the instance name: result of action = self.toolmenu.addAction("Category " + str(i))
-
ekhumoro about 10 years
-
alphanumeric about 10 yearsThanks! Almost there!
-
alphanumeric about 10 yearsIf no .addAction() actions were added to QMenu then clicking on QToolButton brings a Warining: void QCocoaWindow::syncWindowState(Qt::WindowState) invalid window content view size, check your window geometry I wonder if it is a .setPopupMode method that triggers it? Should be QtGui.QToolButton "unset" from .setPopupMode(QtGui.QToolButton.InstantPopup) if there are no actions connected?
-
ekhumoro about 10 years@Sputnix. Not sure, because I can't test on OSX (I don't get any errors on Linux). Maybe you should only set the menu on the button once you have actions to add to it.
-
alphanumeric about 10 yearsThanks! If I figure this out I'll let you know. Otherwise it works great! Thanks again!
-
alphanumeric about 10 yearsAgree. But I have too little GUI space for that one.