python - 带索引恢复的 QListView

标签 python python-3.x pyqt pyqt5 qlistview

作为我上一篇文章的另一个问题的延伸。拥有QListView,可以保存和恢复QListview中项目的选择。恢复后所选项目的索引无法正确打印。

使用currentchange - slot方法更改索引,它会打印QListView中所选项目的正确索引。但是重新运行软件并恢复值后,通过按确定按钮而不更改任何项目,当前索引应该对应于所选项目,但在这种情况下只打印0? 它缺少什么?

enter image description here

import sys
from PyQt5 import QtCore, QtGui, QtWidgets


class Widget(QtWidgets.QDialog):
    def __init__(self, parent=None):
        super(Widget, self).__init__(parent)
        self.setFont(QtGui.QFont("Helvetica", 8, QtGui.QFont.Normal, italic=False))
        self.setWindowTitle("Getting selected item")
        lay = QtWidgets.QVBoxLayout(self)
        self.button = QtWidgets.QPushButton("Okay")
        self.button.clicked.connect(self.accept)
        self.listView = QtWidgets.QListView()
        lay.setContentsMargins(10, 10, 10, 10)
        lay.addWidget(self.listView)

        self.entry = QtGui.QStandardItemModel()
        self.listView.setModel(self.entry)
        self.listView.setSpacing(4)
        self.listView.setFont(
            QtGui.QFont("Helvetica", 9, QtGui.QFont.Normal, italic=False)
        )
        self.listView.setUniformItemSizes(True)
        self.listView.setFixedSize(300, 150)

        Code_Group = QtWidgets.QGroupBox()
        Code_Group.setTitle("&Selecting and deselecting")
        Code_Group.setLayout(lay)

        Vlay = QtWidgets.QVBoxLayout(self)
        Vlay.addWidget(Code_Group)
        Vlay.addWidget(self.button, alignment=QtCore.Qt.AlignCenter)
        Vlay.setSizeConstraint(Vlay.SetFixedSize)

        self.setWindowFlag(QtCore.Qt.WindowMaximizeButtonHint, True)
        self.read_settings()
        self.listView.selectionModel().currentChanged.connect(self.on_row_changed)

        self.accepted.connect(self.write_settings)

    def on_row_changed(self, current, previous):
        self._INDEX = current.row()
        print('Row %d selected' % current.row())

    def closeEvent(self, event):
        print("closeEvent")
        self.write_settings()
        super(Widget, self).closeEvent(event)

    def read_settings(self):
        settings = QtCore.QSettings("file.ini", QtCore.QSettings.IniFormat)
        settings.beginGroup("listView")
        model = self.listView.model()
        if settings.contains("items"):

            editTriggers = settings.value(
                "editTriggers", type=QtWidgets.QAbstractItemView.EditTriggers
            )
            selectionMode = settings.value(
                "selectionMode", type=QtWidgets.QAbstractItemView.SelectionMode
            )
            selectionBehavior = settings.value(
                "selectionBehavior", type=QtWidgets.QAbstractItemView.SelectionBehavior
            )
            self.listView.setEditTriggers(editTriggers)
            self.listView.setSelectionMode(selectionMode)
            self.listView.setSelectionBehavior(selectionBehavior)

            items = settings.value("items", type=QtCore.QByteArray)
            stream = QtCore.QDataStream(items, QtCore.QIODevice.ReadOnly)
            while not stream.atEnd():
                it = QtGui.QStandardItem()
                stream >> it
                model.appendRow(it)
            selecteditems = settings.value("selecteditems", type=list)
            for row in selecteditems:
                index = model.index(row, 0)
                self.listView.selectionModel().select(
                    index, QtCore.QItemSelectionModel.Select
                )
        else:
            for text in [
                "Itemname1",
                "Itemname2",
                "Itemname3",
                "Itemname4",
                "Itemname5",
            ]:
                it = QtGui.QStandardItem(text)
                model.appendRow(it)
                self.listView.setEditTriggers(
                    QtWidgets.QAbstractItemView.NoEditTriggers
                )
                self.listView.setSelectionMode(
                    QtWidgets.QAbstractItemView.SingleSelection
                )
                self.listView.setSelectionBehavior(
                    QtWidgets.QAbstractItemView.SelectRows
                )
        settings.endGroup()

    def write_settings(self):
        settings = QtCore.QSettings("file.ini", QtCore.QSettings.IniFormat)
        settings.beginGroup("listView")
        model = self.listView.model()

        settings.setValue("editTriggers", self.listView.editTriggers())
        settings.setValue("selectionMode", self.listView.selectionMode())
        settings.setValue("selectionBehavior", self.listView.selectionBehavior())

        items = QtCore.QByteArray()
        stream = QtCore.QDataStream(items, QtCore.QIODevice.WriteOnly)
        for i in range(model.rowCount()):
            it = model.item(i)
            stream << it
        settings.setValue("items", items)

        selecteditems = []
        for index in self.listView.selectionModel().selectedRows():
            selecteditems.append(index.row())
        settings.setValue("selecteditems", selecteditems)
        settings.endGroup()


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

最佳答案

您正在监视 currentIndex,希望选择索引也会修改 currentIndex,但这是不正确的。如果您希望恢复 currentIndex,则还必须保存并恢复它。

import sys
from PyQt5 import QtCore, QtGui, QtWidgets


class Widget(QtWidgets.QDialog):
    def __init__(self, parent=None):
        super(Widget, self).__init__(parent)
        self.setFont(QtGui.QFont("Helvetica", 8, QtGui.QFont.Normal, italic=False))
        self.setWindowTitle("Getting selected item")
        lay = QtWidgets.QVBoxLayout(self)
        self.button = QtWidgets.QPushButton("Okay")
        self.button.clicked.connect(self.accept)
        self.listView = QtWidgets.QListView()
        lay.setContentsMargins(10, 10, 10, 10)
        lay.addWidget(self.listView)

        self.entry = QtGui.QStandardItemModel()
        self.listView.setModel(self.entry)
        self.listView.setSpacing(4)
        self.listView.setFont(
            QtGui.QFont("Helvetica", 9, QtGui.QFont.Normal, italic=False)
        )
        self.listView.setUniformItemSizes(True)
        self.listView.setFixedSize(300, 150)

        Code_Group = QtWidgets.QGroupBox()
        Code_Group.setTitle("&Selecting and deselecting")
        Code_Group.setLayout(lay)

        Vlay = QtWidgets.QVBoxLayout(self)
        Vlay.addWidget(Code_Group)
        Vlay.addWidget(self.button, alignment=QtCore.Qt.AlignCenter)
        Vlay.setSizeConstraint(Vlay.SetFixedSize)

        self.setWindowFlag(QtCore.Qt.WindowMaximizeButtonHint, True)

        self.listView.selectionModel().currentChanged.connect(self.on_row_changed)
        self.accepted.connect(self.write_settings)

        self.read_settings()

    def on_row_changed(self, current, previous):
        self._INDEX = current.row()
        print("Row %d selected" % current.row())

    def closeEvent(self, event):
        print("closeEvent")
        self.write_settings()
        super(Widget, self).closeEvent(event)

    def read_settings(self):
        settings = QtCore.QSettings("file.ini", QtCore.QSettings.IniFormat)
        settings.beginGroup("listView")
        model = self.listView.model()
        if settings.contains("items"):

            editTriggers = settings.value(
                "editTriggers", type=QtWidgets.QAbstractItemView.EditTriggers
            )
            selectionMode = settings.value(
                "selectionMode", type=QtWidgets.QAbstractItemView.SelectionMode
            )
            selectionBehavior = settings.value(
                "selectionBehavior", type=QtWidgets.QAbstractItemView.SelectionBehavior
            )
            self.listView.setEditTriggers(editTriggers)
            self.listView.setSelectionMode(selectionMode)
            self.listView.setSelectionBehavior(selectionBehavior)

            items = settings.value("items", type=QtCore.QByteArray)
            stream = QtCore.QDataStream(items, QtCore.QIODevice.ReadOnly)
            while not stream.atEnd():
                it = QtGui.QStandardItem()
                stream >> it
                model.appendRow(it)
            selecteditems = settings.value("selecteditems", type=list)
            for row in selecteditems:
                index = model.index(row, 0)
                self.listView.selectionModel().setCurrentIndex(
                    index, QtCore.QItemSelectionModel.SelectCurrent
                )
            row = settings.value("currentrow", 0, type=int)
            ix = model.index(row, 0)
            self.listView.setCurrentIndex(ix)
        else:
            for text in [
                "Itemname1",
                "Itemname2",
                "Itemname3",
                "Itemname4",
                "Itemname5",
            ]:
                it = QtGui.QStandardItem(text)
                model.appendRow(it)
                self.listView.setEditTriggers(
                    QtWidgets.QAbstractItemView.NoEditTriggers
                )
                self.listView.setSelectionMode(
                    QtWidgets.QAbstractItemView.SingleSelection
                )
                self.listView.setSelectionBehavior(
                    QtWidgets.QAbstractItemView.SelectRows
                )
        settings.endGroup()

    def write_settings(self):
        settings = QtCore.QSettings("file.ini", QtCore.QSettings.IniFormat)
        settings.beginGroup("listView")
        model = self.listView.model()

        settings.setValue("editTriggers", self.listView.editTriggers())
        settings.setValue("selectionMode", self.listView.selectionMode())
        settings.setValue("selectionBehavior", self.listView.selectionBehavior())

        items = QtCore.QByteArray()
        stream = QtCore.QDataStream(items, QtCore.QIODevice.WriteOnly)
        for i in range(model.rowCount()):
            it = model.item(i)
            stream << it
        settings.setValue("items", items)

        selecteditems = []
        for index in self.listView.selectionModel().selectedRows():
            selecteditems.append(index.row())
        settings.setValue("selecteditems", selecteditems)

        settings.setValue("currentrow", self.listView.currentIndex().row())
        settings.endGroup()


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

关于python - 带索引恢复的 QListView,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59331563/

相关文章:

python - 使用 Python 3 阻止 Windows 10 关机

python - 扩展 QSpinBox ContextMenu

python - 根据 QLabel 包含的文本自动调整 QLabel 的大小

python - 使用 Argparse 从相对路径获取完整路径

python - firefox webdriver for selenium on debian issue

python - 使用 Tkinter 显示条目文本时出现问题

python - 如何检测python代码中的内存泄漏?

python 3 : importing different python modules with same name

Python:如何使用不同的基类 rebase 或动态替换类

python - 如何使用 JupyterLab 循环更新交互式图形