Название: QComboBox с множественным выбором
Отправлено: sergs от Март 14, 2017, 12:42
Потребовался выпадающий список с возможностью выбора нескольких элементов. Создал модель, которая автоматически устанавливает всем элементам флажок Qt.ItemIsUserCheckable. Создал класс-наследник QComboBox, использующий эту модель. Вот код class CheckableItemsModel(QStandardItemModel):
checkStateChanged = pyqtSignal()
def __init__(self, parent=None): super(CheckableItemsModel, self).__init__(parent)
def flags(self, index): return super(CheckableItemsModel, self).flags(index) | Qt.ItemIsUserCheckable
def data(self, index, role=Qt.DisplayRole): value = super(CheckableItemsModel, self).data(index, role) if index.isValid() and role == Qt.CheckStateRole and value is None: value = Qt.Unchecked return value
def setData(self, index, value, role=Qt.EditRole): ok = super(CheckableItemsModel, self).setData(index, value, role) if ok and role == Qt.CheckStateRole: self.checkStateChanged.emit()
return ok
class CheckComboBox(QComboBox):
checkedItemsChanged = pyqtSignal(list)
def __init__(self, parent=None): super(CheckComboBox, self).__init__(parent)
# workaround for Mac and GTK to show checkboxes self.setStyleSheet('QComboBox { combobox-popup: 1px }')
self.defaultText = '' self.separator = ',' self.containerPressed = False
self.checkableModel = CheckableItemsModel(self) self.setModel(self.checkableModel)
self.model().checkStateChanged.connect(self.updateCheckedItems) self.model().rowsInserted.connect(self.updateCheckedItems) self.model().rowsRemoved.connect(self.updateCheckedItems)
self.activated.connect(self.toggleCheckState)
def itemCheckState(self, index): return self.itemData(index, Qt.CheckStateRole)
def setItemCheckState(self, index, state): self.setItemData(index, state, Qt.CheckStateRole)
def checkedItems(self): items = list() if self.model(): index = self.model().index(0, self.modelColumn(), self.rootModelIndex()) indexes = self.model().match(index, Qt.CheckStateRole, Qt.Checked, -1, Qt.MatchExactly) for i in indexes: items.append(index.data())
return items
def setCheckedItems(self, items): for i in items: index = self.findText(i) self.setItemCheckState(index, Qt.Checked if index != -1 else Qt.Unchecked)
def updateCheckedItems(self): items = self.checkedItems() if len(items) == 0: self.setEditText(self.defaultText) else: self.setEditText(self.separator.join(items))
self.checkedItemsChanged.emit(items)
def toggleCheckState(self, index): value = self.itemData(index, Qt.CheckStateRole) if value is not None: self.setItemData(index, Qt.Checked if value == Qt.Unchecked else Qt.Unchecked, Qt.CheckStateRole)
Элементы выпадающего списка имеют чекбоксы, но с множественным выбором затык. Сейчас при клике на любой элемент его флажок устанавливается и выпадающий список сразу же закрывается. В какую сторону смотреть, может, что-то не так с моим кодом? И вторая проблема. В Mac и в окружении GTK почему-то не видны чекбоксы, можно ли как-то это исправить, например, при помощи стиля CSS? P.S. Про QListWidget/QListView знаю, нужен именно выпадающий список.
|