如何将所选项目从 QListWidget、QTableWidget 保存到 Qsettings [英] How to save selected Items to Qsettings from QListWidget, QTableWidget

查看:22
本文介绍了如何将所选项目从 QListWidget、QTableWidget 保存到 Qsettings的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

I am Using PyQt5 and Py3.7, I am trying to loop through all my Qlistwidgets and save their string data, but also save all selected items on that widget. I slightly modified the loop from here, but am having some trouble getting the selected items to save and restore using the listwidget array loop. I checked the docs but can't seem to understand how to add additional options into the array (such as save all selected items), from the Qt docs for SetArrayIndex, here.

My listWidgets have selectionMode set to MultiSelection. I am currently saving using this:

def save_list_data(self):
    self.settings = QSettings("data.ini", QSettings.IniFormat)
    for name, obj in inspect.getmembers(self):
        if isinstance(obj, QListWidget):
            name = obj.objectName()
            self.settings.beginWriteArray(name)
            for i in range(obj.count()):
                self.settings.setArrayIndex(i)
                self.settings.setValue(name, obj.item(i).text())
            self.settings.endArray()

And then restoring the listWidget data using:

def open_list_data(self):
    self.settings = QSettings("data.ini", QSettings.IniFormat)
    for name, obj in inspect.getmembers(self):
        if isinstance(obj, QListWidget):
            name = obj.objectName()
            size = self.settings.beginReadArray(name)
            for i in range(size):
                self.settings.setArrayIndex(i)
                value = self.settings.value(name)
                if value != None:
                    obj.addItem(value)
            self.settings.endArray()

This works fine for the data, but how can I get the selectedItems from the ListWidgets to save and restore as well?

解决方案

For my solution take into account the following:

  • Using the inspect module may be beneficial for other libraries, but for Qt the widget is not necessarily a member of the class so it is best to use the Qt introspection itself using findChildren.

  • In the example you use, you are only saving the text but a QListWidgetItem can have more information associated with the roles such as background color, foreground color, etc. So instead I will use the QDataStream operator since this take and save takes the item information.

  • I will use the "objectname/property" format to save the information since the same widget can have several properties that you want to save.

  • To save the information of the selected items, it is only necessary to save the row.

Considering the above, the solution is:

from PyQt5 import QtCore, QtGui, QtWidgets


class Widget(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)

        self.listwidget_1 = QtWidgets.QListWidget(
            objectName="listwidget_1", 
            selectionMode=QtWidgets.QAbstractItemView.MultiSelection
        )
        listwidget_2 = QtWidgets.QListWidget(
            objectName="listwidget_2", 
            selectionMode=QtWidgets.QAbstractItemView.MultiSelection
        )

        lay = QtWidgets.QVBoxLayout(self)
        lay.addWidget(self.listwidget_1)
        lay.addWidget(listwidget_2)

        self.read_settings()

    def closeEvent(self, event):
        self.write_settings()
        super().closeEvent(event)

    def read_settings(self):
        settings = QtCore.QSettings("data.ini", QtCore.QSettings.IniFormat)
        childrens = self.findChildren(QtWidgets.QWidget)
        for children in childrens:
            if isinstance(children, QtWidgets.QListWidget) and children.objectName():
                settings.beginGroup(children.objectName())
                items = settings.value("items")
                selecteditems = settings.value("selecteditems")
                selectionMode = settings.value("selectionMode", type=QtWidgets.QAbstractItemView.SelectionMode)
                children.setSelectionMode(selectionMode)
                # In the first reading the initial values must be established
                if items is None:
                    if children.objectName() == "listwidget_1":
                        for i in range(10):
                            children.addItem(QtWidgets.QListWidgetItem(str(i)))
                    elif children.objectName() == "listwidget_2":
                        for i in "abcdefghijklmnopqrstuvwxyz":
                            children.addItem(QtWidgets.QListWidgetItem(i))
                else:
                    stream = QtCore.QDataStream(items, QtCore.QIODevice.ReadOnly)
                    while not stream.atEnd():
                        it = QtWidgets.QListWidgetItem()
                        stream >> it
                        children.addItem(it)
                    stream = QtCore.QDataStream(selecteditems, QtCore.QIODevice.ReadOnly)
                    while not stream.atEnd():
                        row = stream.readInt()
                        it = children.item(row)
                        it.setSelected(True)
                settings.endGroup()

    def write_settings(self):
        settings = QtCore.QSettings("data.ini", QtCore.QSettings.IniFormat)
        childrens = self.findChildren(QtWidgets.QWidget)
        for children in childrens:
            if isinstance(children, QtWidgets.QListWidget) and children.objectName():
                settings.beginGroup(children.objectName())
                items = QtCore.QByteArray()
                stream = QtCore.QDataStream(items, QtCore.QIODevice.WriteOnly)
                for i in range(children.count()):
                    stream << children.item(i)
                selecteditems = QtCore.QByteArray()
                stream = QtCore.QDataStream(selecteditems, QtCore.QIODevice.WriteOnly)
                for it in children.selectedItems():
                    stream.writeInt(children.row(it))
                settings.setValue("items", items)
                settings.setValue("selecteditems", selecteditems)
                settings.setValue("selectionMode", children.selectionMode())
                settings.endGroup()


if __name__ == "__main__":
    import sys

    app = QtWidgets.QApplication(sys.argv)
    w = Widget()
    w.show()
    sys.exit(app.exec_())

Plus:

import contextlib
from PyQt5 import QtCore, QtGui, QtWidgets


class SettingsManager:
    def __init__(self, filename):
        self.m_settings = QtCore.QSettings(filename, QtCore.QSettings.IniFormat)

    @property
    def settings(self):
        return self.m_settings

    def read(self, widget):
        self.settings.beginGroup(widget.objectName())
        if isinstance(widget, QtWidgets.QAbstractItemView):
            selectionMode = self.settings.value(
                "selectionMode", type=QtWidgets.QAbstractItemView.SelectionMode
            )
            widget.setSelectionMode(selectionMode)
        if isinstance(widget, QtWidgets.QListWidget):
            items = self.settings.value("items")
            selecteditems = self.settings.value("selecteditems")
            # In the first reading the initial values must be established
            if items is None:
                self.read_defaults(widget)
            else:
                stream = QtCore.QDataStream(items, QtCore.QIODevice.ReadOnly)
                while not stream.atEnd():
                    it = QtWidgets.QListWidgetItem()
                    stream >> it
                    widget.addItem(it)
                stream = QtCore.QDataStream(
                    selecteditems, QtCore.QIODevice.ReadOnly
                )
                while not stream.atEnd():
                    row = stream.readInt()
                    it = widget.item(row)
                    if it is not None:
                        it.setSelected(True)
        if isinstance(widget, QtWidgets.QTableWidget):
            rowCount = self.settings.value("rowCount", type=int)
            columnCount = self.settings.value("columnCount", type=int)
            widget.setRowCount(rowCount)
            widget.setColumnCount(columnCount)
            items = self.settings.value("items")
            if items is None:
                self.read_defaults(widget)
            else:
                stream = QtCore.QDataStream(items, QtCore.QIODevice.ReadOnly)
                while not stream.atEnd():
                    it = QtWidgets.QTableWidgetItem()
                    i = stream.readInt()
                    j = stream.readInt()
                    stream >> it
                    widget.setItem(i, j, it)
                selecteditems = self.settings.value("selecteditems")
                stream = QtCore.QDataStream(
                    selecteditems, QtCore.QIODevice.ReadOnly
                )
                while not stream.atEnd():
                    i = stream.readInt()
                    j = stream.readInt()
                    it = widget.item(i, j)
                    if it is not None:
                        it.setSelected(True)
        self.settings.endGroup()

    def write(self, widget):
        self.settings.beginGroup(widget.objectName())
        if isinstance(widget, QtWidgets.QAbstractItemView):
            self.settings.setValue("selectionMode", widget.selectionMode())
        if isinstance(widget, QtWidgets.QListWidget):
            items = QtCore.QByteArray()
            stream = QtCore.QDataStream(items, QtCore.QIODevice.WriteOnly)
            for i in range(widget.count()):
                stream << widget.item(i)
            self.settings.setValue("items", items)
            selecteditems = QtCore.QByteArray()
            stream = QtCore.QDataStream(
                selecteditems, QtCore.QIODevice.WriteOnly
            )
            for it in widget.selectedItems():
                stream.writeInt(widget.row(it))

            self.settings.setValue("selecteditems", selecteditems)
        if isinstance(widget, QtWidgets.QTableWidget):
            self.settings.setValue("rowCount", widget.rowCount())
            self.settings.setValue("columnCount", widget.columnCount())
            items = QtCore.QByteArray()
            stream = QtCore.QDataStream(items, QtCore.QIODevice.WriteOnly)
            for i in range(widget.rowCount()):
                for j in range(widget.columnCount()):
                    it = widget.item(i, j)
                    if it is not None:
                        stream.writeInt(i)
                        stream.writeInt(j)
                        stream << it
            self.settings.setValue("items", items)
            selecteditems = QtCore.QByteArray()
            stream = QtCore.QDataStream(
                selecteditems, QtCore.QIODevice.WriteOnly
            )
            for it in widget.selectedItems():
                # print(it.row(), it.column())
                stream.writeInt(it.row())
                stream.writeInt(it.column())
            self.settings.setValue("selecteditems", selecteditems)
        self.settings.endGroup()

    def release(self):
        self.m_settings.sync()

    def read_defaults(self, widget):
        if widget.objectName() == "listwidget_1":
            widget.setSelectionMode(QtWidgets.QAbstractItemView.MultiSelection)
            for i in range(10):
                widget.addItem(QtWidgets.QListWidgetItem(str(i)))
        elif widget.objectName() == "listwidget_2":
            widget.setSelectionMode(QtWidgets.QAbstractItemView.MultiSelection)
            for i in "abcdefghijklmnopqrstuvwxyz":
                widget.addItem(QtWidgets.QListWidgetItem(i))
        elif widget.objectName() == "tablewidget":
            widget.setSelectionMode(QtWidgets.QAbstractItemView.MultiSelection)
            widget.setRowCount(10)
            widget.setColumnCount(10)
            for i in range(widget.rowCount()):
                for j in range(widget.columnCount()):
                    it = QtWidgets.QTableWidgetItem("{}-{}".format(i, j))
                    widget.setItem(i, j, it)


@contextlib.contextmanager
def settingsContext(filename):
    manager = SettingsManager(filename)
    try:
        yield manager
    finally:
        manager.release()


class Widget(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)

        self.listwidget_1 = QtWidgets.QListWidget(objectName="listwidget_1")
        listwidget_2 = QtWidgets.QListWidget(objectName="listwidget_2")

        tablewidget = QtWidgets.QTableWidget(objectName="tablewidget")

        lay = QtWidgets.QVBoxLayout(self)
        lay.addWidget(self.listwidget_1)
        lay.addWidget(listwidget_2)
        lay.addWidget(tablewidget)

        self.read_settings()

    def closeEvent(self, event):
        self.write_settings()
        super().closeEvent(event)

    def read_settings(self):
        with settingsContext("data.ini") as m:
            for children in self.findChildren(QtWidgets.QWidget):
                if children.objectName():
                    m.read(children)

    def write_settings(self):
        with settingsContext("data.ini") as m:
            for children in self.findChildren(QtWidgets.QWidget):
                if children.objectName():
                    m.write(children)


if __name__ == "__main__":
    import sys

    app = QtWidgets.QApplication(sys.argv)
    w = Widget()
    w.resize(640, 480)
    w.show()
    sys.exit(app.exec_())

这篇关于如何将所选项目从 QListWidget、QTableWidget 保存到 Qsettings的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆