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

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

问题描述

我正在使用PyQt5和Py3.7,试图遍历我所有的Qlistwidgets并保存其字符串数据,还要在该小部件上保存所有选定的项.我从此处略微修改了循环,但是在使用listwidget数组循环获取所选项目进行保存和还原时遇到了一些麻烦.我检查了文档,但似乎无法理解如何从Qt文档中的SetArrayIndex,

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.

我的listWidgets的selectionMode设置为MultiSelection. 我目前正在使用此功能进行保存:

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()

然后使用以下方法还原listWidget数据:

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()

这对于数据来说很好用,但是如何从ListWidgets中获取selectedItem进行保存和恢复?

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:

  • 使用检查模块可能对其他库有利,但是对于Qt,小部件不一定是该类的成员,因此最好使用findChildren本身使用Qt自省.

  • 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.

在您使用的示例中,您只保存了文本,但是QListWidgetItem可以具有与角色相关的更多信息,例如背景色,前景色等.因此,我将使用QDataStream运算符,因为这样做并保存以获取项目信息.

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_())

加号:

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天全站免登陆