QListView Сохранить выбор и проверить все выбранные - PullRequest
0 голосов
/ 18 апреля 2019

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

  • Когда пользователь щелкает элемент в списке, если сделан выбор, он сохраняетвыбранные элементы и изменяет все их флажки в соответствии с флажком выбранного элемента

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

Может ли кто-нибудь помочь мне изменить то, что происходит, когда флажок нажимается для достижения моих целей?

enter image description here

import os, sys
from Qt import QtGui, QtWidgets, QtCore


class CheckableDictionaryListView(QtWidgets.QListView):

    def __init__(self, parent=None, **kwargs):
        super(CheckableDictionaryListView, self).__init__(parent)
        self.resize(300,300)
        self.filters = {}

        self.proxyModel = QtCore.QSortFilterProxyModel()
        self.proxyModel.setSortCaseSensitivity(QtCore.Qt.CaseInsensitive)
        self.proxyModel.setSourceModel(QtGui.QStandardItemModel())
        self.setModel(self.proxyModel)
        self.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
        self.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection)
        self.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
        self.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred)
        self.setContextMenuPolicy(QtCore.Qt.ActionsContextMenu)

        # Begin
        self.setItems(['item 00','item 01','item 02','item 03','item 05','item 06','item 07','item 08','item 09','item 10'])


    # Methods
    def setItems(self, lst):
        model = self.model().sourceModel()
        model.clear()
        for x in lst:
            item = QtGui.QStandardItem()
            item.setCheckable(True)
            item.setData(x, role=QtCore.Qt.DisplayRole)
            model.appendRow(item)


def main():
    app = QtWidgets.QApplication(sys.argv)
    ex = CheckableDictionaryListView()
    ex.show()
    sys.exit(app.exec_())

if __name__ == '__main__':
    pass
    main()

1 Ответ

1 голос
/ 18 апреля 2019

Вы должны использовать QAbstractItemView::MultiSelection в качестве selectionMode в дополнение к перезаписи метода editorEvent, чтобы запретить представлению обрабатывать событие click при его нажатии в флажке:

import os, sys
from Qt import QtGui, QtWidgets, QtCore


class StyledItemDelegate(QtWidgets.QStyledItemDelegate):
    def editorEvent(self, event, model, option, index):
        last_state = index.data(QtCore.Qt.CheckStateRole)
        val = super(StyledItemDelegate, self).editorEvent(
            event, model, option, index
        )
        if last_state != index.data(QtCore.Qt.CheckStateRole):
            return True
        return val


class CheckableDictionaryListView(QtWidgets.QListView):
    def __init__(self, parent=None):
        super(CheckableDictionaryListView, self).__init__(parent)
        delegate = StyledItemDelegate(self)
        self.setItemDelegate(delegate)
        self.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
        self.setSelectionMode(QtWidgets.QAbstractItemView.MultiSelection)
        self.setSizePolicy(
            QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred
        )
        self.setContextMenuPolicy(QtCore.Qt.ActionsContextMenu)
        self.resize(300, 300)

        self.proxyModel = QtCore.QSortFilterProxyModel()
        self.proxyModel.setSortCaseSensitivity(QtCore.Qt.CaseInsensitive)
        self.proxyModel.setSourceModel(QtGui.QStandardItemModel(self))
        self.setModel(self.proxyModel)

        # after set model
        self.model().dataChanged.connect(self.onDataChanged)
        self.setItems(
            [
                "item 00",
                "item 01",
                "item 02",
                "item 03",
                "item 05",
                "item 06",
                "item 07",
                "item 08",
                "item 09",
                "item 10",
            ]
        )

    def setItems(self, lst):
        model = self.model().sourceModel()
        model.clear()
        for x in lst:
            item = QtGui.QStandardItem()
            item.setCheckable(True)
            item.setData(x, role=QtCore.Qt.DisplayRole)
            model.appendRow(item)

    @QtCore.Slot("QModelIndex", "QModelIndex", int)
    def onDataChanged(self, tl, br, roles):
        if QtCore.Qt.CheckStateRole in roles:
            if tl == br and tl in self.selectedIndexes():
                state = tl.data(QtCore.Qt.CheckStateRole)
                self.model().blockSignals(True)
                for ix in self.selectedIndexes():
                    self.model().setData(ix, state, QtCore.Qt.CheckStateRole)
                self.model().blockSignals(False)


def main():

    app = QtWidgets.QApplication(sys.argv)
    app.setStyle("fusion")
    ex = CheckableDictionaryListView()
    ex.show()
    sys.exit(app.exec_())


if __name__ == "__main__": 
    main()
...