PySide:QSettings 作为类变量具有不一致的行为
Posted
技术标签:
【中文标题】PySide:QSettings 作为类变量具有不一致的行为【英文标题】:PySide: QSettings as class variable has inconsistent behavior 【发布时间】:2015-02-19 22:58:55 【问题描述】:我们为 Maya 2015 编写了许多 PySide 脚本,并使用 QSettings
保存设置。通常我们在“readSettings”和“writeSettings”函数中创建QSettings
对象。今天我尝试将QSettings
对象设为类变量。但这造成了一些奇怪的影响。某些通常返回为 <type 'unicode'>
的值开始返回为 <type 'bool'>
,但并非一直如此!
这是我为说明问题而编写的测试脚本:
import shiboken
from PySide import QtGui, QtCore
from maya import OpenMayaUI
#------------------------------------------------------------------------------
def getMayaMainWindow():
parentWindow = OpenMayaUI.MQtUtil.mainWindow()
if parentWindow:
return shiboken.wrapInstance(long(parentWindow), QtGui.QWidget)
#------------------------------------------------------------------------------
class TestQSettingsWin(QtGui.QMainWindow):
def __init__(self, parent=getMayaMainWindow()):
super(TestQSettingsWin, self).__init__(parent)
self.setWindowTitle('Test QSettings')
self.setObjectName('testAllMMessagesWindow')
self.centralWidget = QtGui.QWidget()
self.setCentralWidget(self.centralWidget)
self.mainLayout = QtGui.QVBoxLayout(self.centralWidget)
self.checkBox = QtGui.QCheckBox('check box')
self.mainLayout.addWidget(self.checkBox)
self.readSettings()
def closeEvent(self, event):
self.writeSettings()
def getQSettingsLocation(self):
raise NotImplementedError('Subclasses of TestQSettingsWin need to '
'implement "getQSettingsLocation"".')
def readSettings(self):
setting = self.getQSettingsLocation()
self.restoreGeometry(setting.value('geometry'))
self.restoreState(setting.value('windowState'))
print type(setting.value('checkBox'))
def writeSettings(self):
setting = self.getQSettingsLocation()
setting.setValue('geometry', self.saveGeometry())
setting.setValue('windowState', self.saveState())
setting.setValue('checkBox', self.checkBox.isChecked())
#------------------------------------------------------------------------------
class TestQSettingsClassVar(TestQSettingsWin):
savedSettings = QtCore.QSettings(QtCore.QSettings.IniFormat,
QtCore.QSettings.UserScope,
"Test",
"TestQSettings1")
def getQSettingsLocation(self):
return self.savedSettings
#------------------------------------------------------------------------------
class TestQSettingsDefScope(TestQSettingsWin):
def getQSettingsLocation(self):
setting = QtCore.QSettings(QtCore.QSettings.IniFormat,
QtCore.QSettings.UserScope,
"Test",
"TestQSettings3")
return setting
#------------------------------------------------------------------------------
def showTestWindows():
test1 = TestQSettingsClassVar()
test1.setAttribute(QtCore.Qt.WA_DeleteOnClose, True)
test1.show()
test2 = TestQSettingsDefScope()
test2.setAttribute(QtCore.Qt.WA_DeleteOnClose, True)
test2.show()
以下是在交互式会话中运行它的结果:
>>> import testQSettings
>>> testQSettings.showTestWindows()
<type 'NoneType'>
<type 'NoneType'>
>>> testQSettings.showTestWindows()
<type 'bool'>
<type 'unicode'>
>>> testQSettings.showTestWindows()
<type 'bool'>
<type 'unicode'>
>>> reload(testQSettings)
# Result: <module 'testQSettings' from 'C:/Users/becca/Documents/maya/2015-x64/scripts\testQSettings.pyc'> #
>>> testQSettings.showTestWindows()
<type 'unicode'>
<type 'unicode'>
>>> testQSettings.showTestWindows()
<type 'bool'>
<type 'unicode'>
>>> testQSettings.showTestWindows()
<type 'bool'>
<type 'unicode'>
如您所见,在需要时创建QSettings
对象始终会为数据值返回<type 'unicode'>
结果。但是将QSettings
对象创建为类变量会在重新加载模块时返回<type 'bool'>
结果except,然后返回<type 'unicode'>
。
谁能解释这种奇怪的行为?有没有规定我不应该将 QSettings
对象设为类变量?
【问题讨论】:
【参考方案1】:设置对象必须先将各种不同类型的值序列化为字节,然后再将其写入磁盘。这通常在删除设置对象时完成(或者,如果事件循环正在运行,未保存的数据可能会定期刷新到磁盘)。
在未保存的数据未刷新到磁盘的所有时间,无论何时调用settings.value()
,它都会返回其原始类型的未序列化值。
可以通过调用settings.sync()
自己强制刷新数据,但我强烈建议不要尝试此操作。每当您想读取或写入值时,您都应该始终创建一个新的QSettings
对象,并确保在使用后将其删除。这应该足以保证一致性。
【讨论】:
啊,我明白了。因此,当我第一次创建QSettings
对象并调用 settings.value()
时,它会从 INI 文件中读取序列化(unicode)值。如果我然后继续使用相同的QSettings
对象并调用settings.setValue()
,它将未序列化(布尔)值存储在内存中。如果我然后使用相同的QSettings
对象再次调用settings.value()
,它会看到该键已经在内存中,因此它会获取该值,这仍然是一个布尔值。所以如果我想保证总是得到一个unicode值,我需要创建一个新的QSettings
对象。以上是关于PySide:QSettings 作为类变量具有不一致的行为的主要内容,如果未能解决你的问题,请参考以下文章
Qt - pyside - saveGeometry() saveState()
Qt软件开发-QSettings管理用户环境变量(修改输出)
将Qcombobox的Qsettings写入文件而不关闭Widget