对于我的解决方案,请考虑以下因素:
使用inspect模块对于其他库可能是有益的,但是对于Qt,小部件不一定是该类的成员,因此最好使用findChildren使用Qt自省。
在您使用的示例中,您仅保存文本,但是QListWidgetItem可以具有与角色相关的更多信息,例如背景色,前景色等。因此,我将使用QDataStream运算符,因为这种“获取并保存”获取项信息。
我将使用“对象名称/属性”格式来保存信息,因为同一个窗口小部件可以具有要保存的多个属性。
要保存所选项目的信息,只需保存该行。
考虑到上述情况,解决方案是:
from PyQt5 import QtCore, QtGui, QtWidgetsclass 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 contextlibfrom PyQt5 import QtCore, QtGui, QtWidgetsclass 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.contextmanagerdef 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_())


