Уведомления

Группа в Telegram: @pythonsu

#1 Март 13, 2017 15:08:37

_alexs_
Зарегистрирован: 2012-04-02
Сообщения: 42
Репутация: +  0  -
Профиль   Отправить e-mail  

QComboBox с множественным выбором

Потребовалась возможность множественного выбора элементов в QComboBox. Для этого создал модель, которая автоматически устанавливает элементам флажок 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)

В таком combobox'е элементы можно активировать и деактивировать. Но есть две проблемы, которые пока не могу решить:
  1. не работает множественный выбор. Т.е. можно выбрать только один элемент, и сразу после этого выпадающий список закрывается
  2. под Mac и GTK почему-то не отображаются чекбоксы, при этом в WIndows и KDE все отлично. Это не так критично, скорее всего, можно как-то решить при помощи стилей.

Буду признателен за помощь

Офлайн

#2 Март 14, 2017 23:42:47

PEHDOM
Зарегистрирован: 2016-11-28
Сообщения: 2196
Репутация: +  294  -
Профиль   Отправить e-mail  

QComboBox с множественным выбором

жесть какая… зачем придумывать велосипед?
http://stackoverflow.com/a/22775990
и допиливайте как вам нравится



==============================
Помещайте код в теги:
[code python][/code]
Бериегите свое и чужое время.

Отредактировано PEHDOM (Март 14, 2017 23:44:23)

Офлайн

#3 Март 15, 2017 09:28:28

_alexs_
Зарегистрирован: 2012-04-02
Сообщения: 42
Репутация: +  0  -
Профиль   Отправить e-mail  

QComboBox с множественным выбором

PEHDOM
жесть какая… зачем придумывать велосипед?
Почему «жесть»? Использование моделей это нормальный подход. ИМХО, устанавливать ручками каждому элементу флажок, пробегаясь по ним в цикле, менее удобно, особенно, если содержимое меняется динамически.

Ваш пример страдает той же проблемой, что и мой код: при выборе одного элемента выпадающий список закрывается. Т.е. нельзя выбрать все необходимые элементы сразу.

Офлайн

#4 Март 15, 2017 13:00:33

PEHDOM
Зарегистрирован: 2016-11-28
Сообщения: 2196
Репутация: +  294  -
Профиль   Отправить e-mail  

QComboBox с множественным выбором

_alexs_
Почему «жесть»? Использование моделей это нормальный подход.
жесть в самой модели, в моем примере много меньше букаф, хотя ХЗ может вам оно все надо.

_alexs_
Ваш пример страдает той же проблемой, что и мой код: при выборе одного элемента выпадающий список закрывается. Т.е. нельзя выбрать все необходимые элементы сразу.
ну дык это вам надо переопределять hidePopup, а модель тут вообще нипричем.

Модифицировал пример из стековерфлова, вы конечно можете сделать по своему, но общую мысль, я думаю, вы должны уловить.
 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 hidePopup(self):  #переопределяем hidePopup
        if not self.view().underMouse():      ##скрывать выпадающий список только если курсор не над списком
            QtGui.QComboBox.hidePopup(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)
        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_())



==============================
Помещайте код в теги:
[code python][/code]
Бериегите свое и чужое время.

Отредактировано PEHDOM (Март 15, 2017 15:42:09)

Офлайн

#5 Март 15, 2017 13:35:56

Rodegast
От: Пятигорск
Зарегистрирован: 2007-12-28
Сообщения: 2679
Репутация: +  182  -
Профиль   Отправить e-mail  

QComboBox с множественным выбором

Жесть не в модели, а в самой задачи. Для множественного выбора ComboBox по определению не предназначен.



С дураками и сектантами не спорю, истину не ищу.
Ели кому-то правда не нравится, то заранее извиняюсь.

Офлайн

#6 Июль 19, 2018 08:16:19

anton666
Зарегистрирован: 2018-07-19
Сообщения: 8
Репутация: +  0  -
Профиль   Отправить e-mail  

QComboBox с множественным выбором

А подскажите пожалуйста, как кроме использования ComboBox, реализовать список со множественным выбором?

Офлайн

#7 Июль 19, 2018 09:15:16

PEHDOM
Зарегистрирован: 2016-11-28
Сообщения: 2196
Репутация: +  294  -
Профиль   Отправить e-mail  

QComboBox с множественным выбором

anton666
А подскажите пожалуйста, как кроме использования ComboBox, реализовать список со множественным выбором?
да как угодно, комбобокс это скорее от боезысхожности. А вообще для этого придумали специально чекбоксы.



==============================
Помещайте код в теги:
[code python][/code]
Бериегите свое и чужое время.

Отредактировано PEHDOM (Июль 19, 2018 09:15:31)

Офлайн

#8 Июль 19, 2018 10:30:30

anton666
Зарегистрирован: 2018-07-19
Сообщения: 8
Репутация: +  0  -
Профиль   Отправить e-mail  

QComboBox с множественным выбором

В смысле специальные? Мне необходимо реализовать некий список, в котором можно выбрать сразу несколько значений.
Как это чекбоксами реализовать? Создать отдельное окно на котором будут располагаться подписанные чекбоксы?

Офлайн

#9 Июль 19, 2018 12:58:38

PEHDOM
Зарегистрирован: 2016-11-28
Сообщения: 2196
Репутация: +  294  -
Профиль   Отправить e-mail  

QComboBox с множественным выбором

anton666
Как это чекбоксами реализовать? Создать отдельное окно на котором будут располагаться подписанные чекбоксы?
тут все зависит от ваших задач\дизайна, есть еще QListWidget, собственно тоже для этого придуман, есть чекбоксы которые можно обьединить в фрейме/виджете, даже можно извратиться и QTableWidget для этого использовать.



==============================
Помещайте код в теги:
[code python][/code]
Бериегите свое и чужое время.

Офлайн

#10 Июль 19, 2018 16:57:19

KriO
Зарегистрирован: 2012-10-07
Сообщения: 61
Репутация: +  9  -
Профиль   Отправить e-mail  

QComboBox с множественным выбором

PEHDOM
На мой взгляд, QTableWidget - самый подходящий простой вариант для такой задачи.

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version