关闭应用程序后如何在 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)
我在 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)