I'm quite new in the world of programming in python. I'm coding a GUI that allows users to insert some data. I'm using PyQt5 and trying to use some functions to save and reload widgets state from the .ini file after reopening the app. That's just an example of code:
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_())
I'd like to save and reload items from the QListWidgets in my form. At the moment it doesn't happen. Any help and suggestion is appreciated. Thanks
#UPDATE:
Thanks @NicholasTJ I think that's very usefull. Just one last question. As first parameter of
def gui_save(ui: QWidget, settings: QSettings, uiName="uiwidget")
when I call this method and use "self", it seems is not working.
That's an example linking to my first answer:
gui_save(self, self.settings, MyForm)
These are the definitions I'm trying to use:
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()
I resolved finally using these functions. Hope this could be usefull for someone is needing a working gui save and restore.
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)