Python PyQt4 функции для сохранения и восстановления значений виджета пользовательского интерфейса?
Прежде чем я попытаюсь написать свои собственные функции модуля Python PyQt4... Я хотел спросить, есть ли у кого такая функция для обмена.
Во многих моих программах python, где у меня есть графический интерфейс, построенный с использованием PyQt4 и qtDesigner, я использую метод QSettings для сохранения и восстановления состояний пользовательского интерфейса и значений всех виджетов во время закрытия и запуска.
В этом примере показано, как я сохраняю и восстанавливаю некоторые поля lineEdit, checkBox и radioButton.
Есть ли у кого-нибудь функция, которая может пересекать пользовательский интерфейс и находить ВСЕ виджеты/элементы управления и их состояния и сохранять их (например, guisave()) и другую функцию, которая может их восстановить (например, guirestore())?
My closeEvent выглядит примерно так:
#---------------------------------------------
# close by x OR call to self.close
#---------------------------------------------
def closeEvent(self, event): # user clicked the x or pressed alt-F4...
UI_VERSION = 1 # increment this whenever the UI changes significantly
programname = os.path.basename(__file__)
programbase, ext = os.path.splitext(programname) # extract basename and ext from filename
settings = QtCore.QSettings("company", programbase)
settings.setValue("geometry", self.saveGeometry()) # save window geometry
settings.setValue("state", self.saveState(UI_VERSION)) # save settings (UI_VERSION is a constant you should increment when your UI changes significantly to prevent attempts to restore an invalid state.)
# save ui values, so they can be restored next time
settings.setValue("lineEditUser", self.lineEditUser.text());
settings.setValue("lineEditPass", self.lineEditPass.text());
settings.setValue("checkBoxReplace", self.checkBoxReplace.checkState());
settings.setValue("checkBoxFirst", self.checkBoxFirst.checkState());
settings.setValue("radioButton1", self.radioButton1.isChecked());
sys.exit() # prevents second call
My MainWindow init выглядит примерно так:
def __init__(self, parent = None):
# initialization of the superclass
super(QtDesignerMainWindow, self).__init__(parent)
# setup the GUI --> function generated by pyuic4
self.setupUi(self)
#---------------------------------------------
# restore gui position and restore fields
#---------------------------------------------
UI_VERSION = 1
settings = QtCore.QSettings("company", programbase) # http://pyqt.sourceforge.net/Docs/PyQt4/pyqt_qsettings.html
self.restoreGeometry(settings.value("geometry"))
self.restoreState(settings.value("state"),UI_VERSION)
self.lineEditUser.setText(str(settings.value("lineEditUser"))) # restore lineEditFile
self.lineEditPass.setText(str(settings.value("lineEditPass"))) # restore lineEditFile
if settings.value("checkBoxReplace") != None:
self.checkBoxReplace.setCheckState(settings.value("checkBoxReplace")) # restore checkbox
if settings.value("checkBoxFirst") != None:
self.checkBoxFirst.setCheckState(settings.value("checkBoxFirst")) # restore checkbox
value = settings.value("radioButton1").toBool()
self.ui.radioButton1.setChecked(value)
Ответы
Ответ 1
ОК, я написал модуль с 2 функциями, чтобы делать то, о чем я просил.
На самом деле это не так сложно, как только я это понял, но он действительно экономит много времени, когда вы создаете новые программы guq pyqt, где вы хотите сохранить значения полей виджета между сеансами.
Я в настоящее время только поля LineEdit, checkBox и поля combobox закодированы. Если кто-то хочет добавить или улучшить (например, радиокнопки... и т.д.)... Я уверен, что другие, включая меня, оценят это.
#===================================================================
# Module with functions to save & restore qt widget values
# Written by: Alan Lilly
# Website: http://panofish.net
#===================================================================
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
import inspect
#===================================================================
# save "ui" controls and values to registry "setting"
# currently only handles comboboxes editlines & checkboxes
# ui = qmainwindow object
# settings = qsettings object
#===================================================================
def guisave(ui, settings):
#for child in ui.children(): # works like getmembers, but because it traverses the hierarachy, you would have to call guisave recursively to traverse down the tree
for name, obj in inspect.getmembers(ui):
#if type(obj) is QComboBox: # this works similar to isinstance, but missed some field... not sure why?
if isinstance(obj, QComboBox):
name = obj.objectName() # get combobox name
index = obj.currentIndex() # get current index from combobox
text = obj.itemText(index) # get the text for current index
settings.setValue(name, text) # save combobox selection to registry
if isinstance(obj, QLineEdit):
name = obj.objectName()
value = obj.text()
settings.setValue(name, value) # save ui values, so they can be restored next time
if isinstance(obj, QCheckBox):
name = obj.objectName()
state = obj.checkState()
settings.setValue(name, state)
#===================================================================
# restore "ui" controls with values stored in registry "settings"
# currently only handles comboboxes, editlines &checkboxes
# ui = QMainWindow object
# settings = QSettings object
#===================================================================
def guirestore(ui, settings):
for name, obj in inspect.getmembers(ui):
if isinstance(obj, QComboBox):
index = obj.currentIndex() # get current region from combobox
#text = obj.itemText(index) # get the text for new selected index
name = obj.objectName()
value = unicode(settings.value(name))
if value == "":
continue
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):
name = obj.objectName()
value = unicode(settings.value(name)) # get stored value from registry
obj.setText(value) # restore lineEditFile
if isinstance(obj, QCheckBox):
name = obj.objectName()
value = settings.value(name) # get stored value from registry
if value != None:
obj.setCheckState(value) # restore checkbox
#if isinstance(obj, QRadioButton):
################################################################
if __name__ == "__main__":
# execute when run directly, but not when called as a module.
# therefore this section allows for testing this module!
#print "running directly, not as a module!"
sys.exit()
Ответ 2
Здесь обновленный фрагмент, изначально принадлежащий mr. Panofish. Эти прекрасные функции такие же, но теперь они могут быть использованы на любых версиях PyQt и Python с небольшими изменениями, если это необходимо. спасибо mr. Panofish, долго жить OpenSource!:)
Изменения:
- Обновлено для Python3 и PyQt5
- Добавлена геометрия save\restore
- Добавлен QRadioButton save\restore
-
SetCheckState() заменен SetChecked(), чтобы избежать tristate
def guisave(self):
# Save geometry
self.settings.setValue('size', self.size())
self.settings.setValue('pos', self.pos())
for name, obj in inspect.getmembers(ui):
# if type(obj) is QComboBox: # this works similar to isinstance, but missed some field... not sure why?
if isinstance(obj, QComboBox):
name = obj.objectName() # get combobox name
index = obj.currentIndex() # get current index from combobox
text = obj.itemText(index) # get the text for current index
settings.setValue(name, text) # save combobox selection to registry
if isinstance(obj, QLineEdit):
name = obj.objectName()
value = obj.text()
settings.setValue(name, value) # save ui values, so they can be restored next time
if isinstance(obj, QCheckBox):
name = obj.objectName()
state = obj.isChecked()
settings.setValue(name, state)
if isinstance(obj, QRadioButton):
name = obj.objectName()
value = obj.isChecked() # get stored value from registry
settings.setValue(name, value)
def guirestore(self):
# Restore geometry
self.resize(self.settings.value('size', QtCore.QSize(500, 500)))
self.move(self.settings.value('pos', QtCore.QPoint(60, 60)))
for name, obj in inspect.getmembers(ui):
if isinstance(obj, QComboBox):
index = obj.currentIndex() # get current region from combobox
# text = obj.itemText(index) # get the text for new selected index
name = obj.objectName()
value = (settings.value(name))
if value == "":
continue
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):
name = obj.objectName()
value = (settings.value(name).decode('utf-8')) # get stored value from registry
obj.setText(value) # restore lineEditFile
if isinstance(obj, QCheckBox):
name = obj.objectName()
value = settings.value(name) # get stored value from registry
if value != None:
obj.setChecked(strtobool(value)) # restore checkbox
if isinstance(obj, QRadioButton):
name = obj.objectName()
value = settings.value(name) # get stored value from registry
if value != None:
obj.setChecked(strtobool(value))
Ответ 3
спасибо Панофиш и все
Я добавляю некоторое обновление для QSlider/QSpinBox.
он маленький и простой.
в guisave вы можете добавить:
if isinstance(obj, QSpinBox):
name = obj.objectName()
value = obj.value() # get stored value from registry
settings.setValue(name, value)
if isinstance(obj, QSlider):
name = obj.objectName()
value = obj.value() # get stored value from registry
settings.setValue(name, value)
в guirestore вы можете добавить:
if isinstance(obj, QSlider):
name = obj.objectName()
value = settings.value(name) # get stored value from registry
if value != None:
obj. setValue(int(value)) # restore value from registry
if isinstance(obj, QSpinBox):
name = obj.objectName()
value = settings.value(name) # get stored value from registry
if value != None:
obj. setValue(int(value)) # restore value from registry
Ответ 4
Я добавляю обновление для QListWidget.
В guisave:
if isinstance(obj, QListWidget):
name = obj.objectName()
settings.beginWriteArray(name)
for i in range(obj.count()):
settings.setArrayIndex(i)
settings.setValue(name, obj.item(i).text())
settings.endArray()
в guirestore:
if isinstance(obj, QListWidget):
name = obj.objectName()
size = settings.beginReadArray(name)
for i in range(size):
settings.setArrayIndex(i)
value = settings.value(name) # get stored value from registry
if value != None:
obj.addItem(value)
settings.endArray()
Ответ 5
Я нашел эти ответы полезными, поэтому я решил собрать их вместе и опубликовать версию (для PySide2/Qt5) с удаленным дублированием и именем для группировки настроек в.
from PySide2.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 GuiSave(ui : QWidget, settings : QSettings, uiName="uiwidget"):
namePrefix = f"{uiName}/"
settings.setValue(namePrefix + "geometry", ui.saveGeometry())
for name, obj in inspect.getmembers(ui):
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 GuiRestore(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()'''