关闭应用程序后如何在 QListWidget 中保存和重新加载项目?

How can I save and reload items in QListWidgets after closing app?

我在 python 的编程领域还很陌生。我正在编写一个允许用户插入一些数据的 GUI。我正在使用 PyQt5 并尝试使用一些函数在重新打开应用程序后从 .ini 文件保存和重新加载小部件状态。 这只是一个代码示例:

from PyQt5.QtCore import *
from PyQt5 import QtCore, QtGui, QtWidgets


class Ui_Form(object):
    def setupUi(self, Form):
        Form.setObjectName("Form")
        Form.resize(366, 376)
        self.pushButton = QtWidgets.QPushButton(Form)
        self.pushButton.setGeometry(QtCore.QRect(60, 70, 93, 28))
        self.pushButton.setObjectName("pushButton")
        self.listWidget = QtWidgets.QListWidget(Form)
        self.listWidget.setGeometry(QtCore.QRect(60, 110, 256, 192))
        self.listWidget.setObjectName("listWidget")
        self.lineEdit = QtWidgets.QLineEdit(Form)
        self.lineEdit.setGeometry(QtCore.QRect(170, 70, 113, 21))
        self.lineEdit.setObjectName("lineEdit")

        self.retranslateUi(Form)
        QtCore.QMetaObject.connectSlotsByName(Form)

    def retranslateUi(self, Form):
        _translate = QtCore.QCoreApplication.translate
        Form.setWindowTitle(_translate("Form", "Form"))
        self.pushButton.setText(_translate("Form", "ADD"))

class MyForm(QtWidgets.QWidget):
    settings = QSettings("gui.ini", QSettings.IniFormat)

    def __init__(self, parent=None):
        QtWidgets.QWidget.__init__(self, parent)
        self.ui = Ui_Form()
        self.ui.setupUi(self)

        restore(self.settings)

        self.ui.pushButton.clicked.connect(self.addbutton)

    def addbutton(self):
        if self.ui.lineEdit.text():
            self.ui.listWidget.addItem(self.ui.lineEdit.text().upper())
            self.ui.lineEdit.setText("")

    def closeEvent(self, event):
        save(self.settings)
        QtWidgets.QWidget.closeEvent(self, event)

def value_is_valid(val):
    if isinstance(val, QtGui.QPixmap):
        return not val.isNull()
    return True


def restore(settings):
    finfo = QtCore.QFileInfo(settings.fileName())

    if finfo.exists() and finfo.isFile():
        for w in QtWidgets.qApp.allWidgets():
            if w.objectName():
                mo = w.metaObject()
                for i in range(mo.propertyCount()):
                    prop = mo.property(i)
                    name = prop.name()
                    last_value = w.property(name)
                    key = "{}/{}".format(w.objectName(), name)
                    if not settings.contains(key):
                        continue
                    val = settings.value(key, type=type(last_value),)
                    if (
                        val != last_value
                        and value_is_valid(val)
                        and prop.isValid()
                        and prop.isWritable()
                    ):
                        w.setProperty(name, val)


def save(settings):
    for w in QtWidgets.qApp.allWidgets():
        if w.objectName():
            mo = w.metaObject()
            for i in range(mo.propertyCount()):
                prop = mo.property(i)
                name = prop.name()
                key = "{}/{}".format(w.objectName(), name)
                val = w.property(name)
                if value_is_valid(val) and prop.isValid() and prop.isWritable():
                    settings.setValue(key, w.property(name))

if __name__ == "__main__":
    import sys

    app = QtWidgets.QApplication(sys.argv)
    form = MyForm()

    form.show()
    sys.exit(app.exec_())

我想在我的表单中保存和重新加载 QListWidgets 中的项目。目前它没有发生。任何帮助和建议表示赞赏。谢谢

#

更新:

谢谢@NicholasTJ,我认为这非常有用。最后一个问题。作为第一个参数 def gui_save(ui: QWidget, settings: QSettings, uiName="uiwidget") 当我调用此方法并使用 "self" 时,它似乎不起作用。 这是链接到我的第一个答案的示例:

gui_save(self, self.settings, MyForm)

这些是我尝试使用的定义:

from PyQt5 import QtWidgets
from PyQt5.QtCore import QSettings
from PyQt5.QtWidgets import *
import inspect


def GetHandledTypes():
    return QComboBox, QLineEdit, QCheckBox, QRadioButton, QSpinBox, QSlider, QListWidget


def IsHandledType(widget):
    return any(isinstance(widget, t) for t in GetHandledTypes())


# ===================================================================
# save "ui" controls and values to registry "setting"
# ===================================================================

def gui_save(ui: QWidget, settings: QSettings, uiName="uiwidget"):
    namePrefix = f"{uiName}/"
    settings.setValue(namePrefix + "geometry", ui.saveGeometry())

    for name, obj in QtWidgets.qApp.allWidgets():
        if not IsHandledType(obj):
            continue

        name = obj.objectName()
        value = None
        if isinstance(obj, QComboBox):
            index = obj.currentIndex()  # get current index from combobox
            value = obj.itemText(index)  # get the text for current index

        if isinstance(obj, QLineEdit):
            value = obj.text()

        if isinstance(obj, QCheckBox):
            value = obj.isChecked()

        if isinstance(obj, QRadioButton):
            value = obj.isChecked()

        if isinstance(obj, QSpinBox):
            value = obj.value()

        if isinstance(obj, QSlider):
            value = obj.value()

        if isinstance(obj, QListWidget):
            settings.beginWriteArray(name)
            for i in range(obj.count()):
                settings.setArrayIndex(i)
                settings.setValue(namePrefix + name, obj.item(i).text())
            settings.endArray()
        elif value is not None:
            settings.setValue(namePrefix + name, value)


# ===================================================================
# restore "ui" controls with values stored in registry "settings"
# ===================================================================

def gui_restore(ui: QWidget, settings: QSettings, uiName="uiwidget"):
    from distutils.util import strtobool

    namePrefix = f"{uiName}/"
    geometryValue = settings.value(namePrefix + "geometry")
    if geometryValue:
        ui.restoreGeometry(geometryValue)

    for name, obj in inspect.getmembers(ui):
        if not IsHandledType(obj):
            continue

        name = obj.objectName()
        value = None
        if not isinstance(obj, QListWidget):
            value = settings.value(namePrefix + name)
            if value is None:
                continue

        if isinstance(obj, QComboBox):
            index = obj.findText(value)  # get the corresponding index for specified string in combobox

            if index == -1:  # add to list if not found
                obj.insertItems(0, [value])
                index = obj.findText(value)
                obj.setCurrentIndex(index)
            else:
                obj.setCurrentIndex(index)  # preselect a combobox value by index

        if isinstance(obj, QLineEdit):
            obj.setText(value)

        if isinstance(obj, QCheckBox):
            obj.setChecked(strtobool(value))

        if isinstance(obj, QRadioButton):
            obj.setChecked(strtobool(value))

        if isinstance(obj, QSlider):
            obj.setValue(int(value))

        if isinstance(obj, QSpinBox):
            obj.setValue(int(value))

        if isinstance(obj, QListWidget):
            size = settings.beginReadArray(namePrefix + name)
            for i in range(size):
                settings.setArrayIndex(i)
                value = settings.value(namePrefix + name)
                if value is not None:
                    obj.addItem(value)
            settings.endArray()

我终于决定使用这些功能。希望这对需要工作的 gui 保存和恢复的人有用。

def gui_save(self):
    save_settings_message()
    for name, obj in inspect.getmembers(self.ui):
        if isinstance(obj, QComboBox):
            name = obj.objectName()
            index = obj.currentIndex()
            text = obj.itemText(index)
            self.settings.setValue(name, text)
        if isinstance(obj, QLineEdit):
            name = obj.objectName()
            value = obj.text()
            self.settings.setValue(name, value)
        if isinstance(obj, QCheckBox):
            name = obj.objectName()
            state = obj.isChecked()
            self.settings.setValue(name, state)
        if isinstance(obj, QRadioButton):
            name = obj.objectName()
            value = obj.isChecked()
            self.settings.setValue(name, value)
        if isinstance(obj, QSpinBox):
            name = obj.objectName()
            value = obj.value()
            self.settings.setValue(name, value)
        if isinstance(obj, QSlider):
            name = obj.objectName()
            value = obj.value()
            self.settings.setValue(name, value)
        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()
        if isinstance(obj, QDateEdit):
            name = obj.objectName()
            value = obj.date()
            self.settings.setValue(name, value)
def gui_restore(self):
    from distutils.util import strtobool
    for name, obj in inspect.getmembers(self.ui):
        if isinstance(obj, QComboBox):
            name = obj.objectName()
            value = (self.settings.value(name))
            if value == "":
                continue
            index = obj.findText(value)
            if index == -1:
                obj.insertItems(0, [value])
                index = obj.findText(value)
                obj.setCurrentIndex(index)
            else:
                obj.setCurrentIndex(index)
        if isinstance(obj, QLineEdit):
            name = obj.objectName()
            value = (self.settings.value(name))
            obj.setText(value)
        if isinstance(obj, QCheckBox):
            name = obj.objectName()
            value = self.settings.value(name)
            if value is not None:
                obj.setChecked(strtobool(value))
        if isinstance(obj, QRadioButton):
            name = obj.objectName()
            value = self.settings.value(name)
            if value is not None:
                obj.setChecked(strtobool(value))
        if isinstance(obj, QSlider):
            name = obj.objectName()
            value = self.settings.value(name)
            if value is not None:
                obj.setValue(int(value))
        if isinstance(obj, QSpinBox):
            name = obj.objectName()
            value = self.settings.value(name)
            if value is not None:
                obj.setValue(int(value))
        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 is not None:
                    obj.addItem(value)
            self.settings.endArray()
        if isinstance(obj, QDateEdit):
            name = obj.objectName()
            value = self.settings.value(name)
            if value is not None:
                obj.setDate(value)