Reputation: 25
I would like to add some kind of parent items to a pyqt5 combobox which allow grouping of the items below. the parents should be not selectable and bold if possible, the children a little bit indented.
What I have got so far: I got them bold but I have no idea about the not-selectable option. I could add .setEnabled(False) but this greys them out. also maybe there is a nicer way than adding simply blanks in front of the children items?
from PyQt5.QtWidgets import QWidget, QComboBox, QApplication
import PyQt5.QtGui
import sys
class Example(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
combo = QComboBox(self)
combo.addItem("option_1")
combo.addItem("group_1")
combo.addItem(" option_2")
combo.addItem(" option_3")
combo.addItem("group_2")
combo.addItem(" option_4")
combo.addItem(" option_5")
font = PyQt5.QtGui.QFont()
font.setBold(True)
item = combo.model().item(1, 0) # group_1 bold
item.setFont(font)
item = combo.model().item(4, 0) # group_2 bold
item.setFont(font)
combo.currentTextChanged.connect(lambda : print(combo.currentText()) )
self.setGeometry(100, 100, 300, 100)
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
how current code looks like:
Upvotes: 2
Views: 1173
Reputation: 244003
You can create a custom model that implements the logic of the groups. To disable the selection you must use the flags. To establish indentation using a delegate next to a role. You should not use the addItem method of the QComboBox but the model.
from PyQt5 import QtCore, QtGui, QtWidgets
GroupRole = QtCore.Qt.UserRole
class GroupDelegate(QtWidgets.QStyledItemDelegate):
def initStyleOption(self, option, index):
super(GroupDelegate, self).initStyleOption(option, index)
if not index.data(GroupRole):
option.text = " " + option.text
class GroupItem(QtGui.QStandardItem):
def __init__(self, text):
super(GroupItem, self).__init__(text)
self.setData(True, GroupRole)
self._number_of_childrens = 0
font = self.font()
font.setBold(True)
self.setFont(font)
self.setFlags(self.flags() & ~QtCore.Qt.ItemIsSelectable)
def addChild(self, text):
it = QtGui.QStandardItem(text)
it.setData(False, GroupRole)
self._number_of_childrens += 1
self.model().insertRow(self.row() + self._number_of_childrens, it)
return it
class GroupComboBox(QtWidgets.QComboBox):
def __init__(self, parent=None):
super(GroupComboBox, self).__init__(parent)
self.setModel(QtGui.QStandardItemModel(self))
delegate = GroupDelegate(self)
self.setItemDelegate(delegate)
def addGroup(self, text):
it = GroupItem(text)
self.model().appendRow(it)
return it
def addChild(self, text):
it = QtGui.QStandardItem(text)
it.setData(True, GroupRole)
self.model().appendRow(it)
class Example(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
combo = GroupComboBox()
combo.addChild("option_1")
group1 = combo.addGroup("group_1")
group1.addChild("option_2")
group1.addChild("option_3")
group2 = combo.addGroup("group_2")
group2.addChild("option_4")
group2.addChild("option_5")
lay = QtWidgets.QVBoxLayout(self)
lay.addWidget(combo)
self.resize(160, 60)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
ex = Example()
ex.show()
sys.exit(app.exec_())
Upvotes: 3