Удалите QCombobox, чтобы показать все данные на панели окна, чтобы пользователь мог выбрать несколько значений одновременно - PullRequest
0 голосов
/ 07 февраля 2020

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

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

Ниже приведен фрагмент кода.

from PyQt5 import QtCore, QtGui, QtWidgets
import sys

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

    def checkedItems(self):
        checkedItems = []
        for index in range(self.count()):
            item = self.model().item(index)
            if item.checkState() == QtCore.Qt.Checked:
                checkedItems.append(item)
        return checkedItems

class Ui_dialogCreateBatch(object):
    def setupUi(self, dialogCreateBatch):
        dialogCreateBatch.resize(400, 338)
        dialogCreateBatch.setMouseTracking(True)

        self.gridLayoutWidget = QtWidgets.QWidget(dialogCreateBatch)
        self.gridLayoutWidget.setGeometry(QtCore.QRect(10, 10, 360, 115))
        self.gridLayoutWidget.setObjectName("gridLayoutWidget")
        self.gridLayout = QtWidgets.QGridLayout(self.gridLayoutWidget)
        self.gridLayout.setContentsMargins(0, 0, 0, 0)
        self.gridLayout.setObjectName("gridLayout")

        self.cboItemList = CheckableComboBox(self.gridLayoutWidget)
        self.cboItemList.setObjectName("cboItemList")
        self.gridLayout.addWidget(self.cboItemList, 0, 0, 1, 1)

        data = ('item1', 'item2', 'item3')

        for index, element in enumerate(data):
            self.cboItemList.addItem(element)
            item = self.cboItemList.model().item(index, 0)
            item.setCheckState(QtCore.Qt.Unchecked)

        self.buttonBox = QtWidgets.QDialogButtonBox(dialogCreateBatch)
        self.buttonBox.setGeometry(QtCore.QRect(100, 300, 156, 23))
        self.buttonBox.setOrientation(QtCore.Qt.Horizontal)

        self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok)
        self.buttonBox.setObjectName("buttonBox")

        self.retranslateUi(dialogCreateBatch)
        QtCore.QMetaObject.connectSlotsByName(dialogCreateBatch)

    def retranslateUi(self, dialogCreateBatch):
        _translate = QtCore.QCoreApplication.translate
        dialogCreateBatch.setWindowTitle(_translate("dialogCreateBatch", "Create Item Batch"))

class DialogCreateBatch(QtWidgets.QDialog, Ui_dialogCreateBatch):
    def __init__(self, parent=None):
        QtWidgets.QDialog.__init__(self, parent)
        self.setupUi(self)
        self.buttonBox.accepted.connect(self.on_accepted)
        self.buttonBox.rejected.connect(self.reject)

    def on_accepted(self):
        selectedItems = self.cboItemList.checkedItems()
        print(selectedItems)
        self.accept()

if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    w = DialogCreateBatch()
    w.show()
    sys.exit(app.exec_())

1 Ответ

1 голос
/ 07 февраля 2020

Следующий код реализует QDialog, который показывает QListView с моделью, которая имеет проверяемые элементы на основе QStandardItemModel:

import sys

from PyQt5 import QtCore, QtGui, QtWidgets


class DialogCreateBatch(QtWidgets.QDialog):
    def __init__(self, parent=None):
        super(DialogCreateBatch, self).__init__(parent)
        self.model = QtGui.QStandardItemModel(self)
        self.view = QtWidgets.QListView()
        self.view.setModel(self.model)

        self.button_box = QtWidgets.QDialogButtonBox()
        self.button_box.setOrientation(QtCore.Qt.Horizontal)
        self.button_box.setStandardButtons(
            QtWidgets.QDialogButtonBox.Cancel | QtWidgets.QDialogButtonBox.Ok
        )
        self.button_box.accepted.connect(self.accept)
        self.button_box.rejected.connect(self.reject)

        lay = QtWidgets.QVBoxLayout(self)
        lay.addWidget(self.view)
        lay.addWidget(self.button_box)

    @property
    def items(self):
        items = []
        for i in range(self.model.rowCount()):
            it = self.model.item(i)
            items.append(it.text())
        return items

    @items.setter
    def items(self, items):
        self.model.clear()
        for item in items:
            it = QtGui.QStandardItem(item)
            it.setCheckable(True)
            self.model.appendRow(it)

    @property
    def checked_items(self):
        checked_items = []
        for i in range(self.model.rowCount()):
            it = self.model.item(i)
            if it.data(QtCore.Qt.CheckStateRole) == QtCore.Qt.Checked:
                checked_items.append(it.text())
        return checked_items


if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    w = DialogCreateBatch()
    w.setWindowTitle("Stack Overflow")
    w.items = ("item1", "item2", "item3")
    if w.exec_() == QtWidgets.QDialog.Accepted:
        print(w.checked_items)
...