使用python 2.7.6/PyQt4处理设置模块中的QVariant
我以前在这个站点和其他平台上读过几个主题,但我的代码仍然不能按预期工作。我似乎不能把所有的拼图拼在一起,需要有人检查我的代码 我正在为QtiPlot程序编写一个插件。我正在使用Python2.7.6和PyQt4。我用QT设计器创建了插件GUI。我也是Python新手。我使用这些“旧”资源是因为我的前任使用过它们 我目前的任务是开发设置,即能够保存和恢复参数。 我在该网站上找到了一个用于此目的的模板: 我想将参数保存到Ini文件中。 然而,我有问题的QV变体。将保存表达式“PyQt4.QtCore.QVariant object at 0x08667FB0”,而不是我在插件中插入的字符串。我已经知道这是一个问题,因为QVariants没有正确地转换回Python对象 因此,为了手动将QVariants转换回来,我在restore函数中的QLineEdit对象的赋值中添加了短语“toString()”(注释掉的那行是以前的版本)。但是插件中我的QLineEdit块是空的,这让我很困惑。我在文档中读到,如果QVariant不包含一个预设类型(包括string),则返回一个空字符串。尽管我之前输入了一个字符串,但这种情况还是发生了 这是否意味着字符串首先没有正确保存?或者它意味着什么,我错过了什么,或者我做错了什么 我还注意到Ini文件中没有存储任何值,因此部分代码仍然存在缺陷。但我不确定这是因为save函数不起作用,还是因为Ini构造本身是错误的 此外,我尝试使用配置文件开头的SIP模块来解决我的问题(它也被注释掉了,因为它到目前为止对我不起作用)。但是,尽管我把它放在了代码的开头,我还是得到了一个错误“API'QVariant'已经设置为版本1”。我不明白SIP指令被覆盖的原因或原因。有办法解决这个问题吗 我的配置程序如下所示:使用python 2.7.6/PyQt4处理设置模块中的QVariant,python,pyqt4,Python,Pyqt4,我以前在这个站点和其他平台上读过几个主题,但我的代码仍然不能按预期工作。我似乎不能把所有的拼图拼在一起,需要有人检查我的代码 我正在为QtiPlot程序编写一个插件。我正在使用Python2.7.6和PyQt4。我用QT设计器创建了插件GUI。我也是Python新手。我使用这些“旧”资源是因为我的前任使用过它们 我目前的任务是开发设置,即能够保存和恢复参数。 我在该网站上找到了一个用于此目的的模板: 我想将参数保存到Ini文件中。 然而,我有问题的QV变体。将保存表达式“PyQt4.QtCore
#import sip
#sip.setapi('QVariant', 2)
#sip.setapi('QString', 2)
import inspect
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
sys.path.append("C:\\Program Files (x86)\\QtiPlot\\app\\02 Python Packages")
import PyQt4_Save_Restore_UI_Widget_Values
class app_conf(QtGui.QWidget):
def __init__(self):
super(self.__class__, self).__init__()
self.version = 1.0
QtCore.QCoreApplication.setOrganizationName("Organization")
QtCore.QCoreApplication.setApplicationName("Application")
QtCore.QSettings.setPath(QSettings.IniFormat, QSettings.UserScope, "C:\\Program Files (x86)\\QtiPlot\\app\\02 Python Packages\\saved.ini")
self.settings = QtCore.QSettings("C:\\Program Files (x86)\\QtiPlot\\app\\02 Python Packages\\saved.ini", QSettings.IniFormat)
from PyQt4 import uic
self.ui = uic.loadUi(r"C:\Program Files (x86)/QtiPlot/app/03 UI Files/Config.ui")
PyQt4_Save_Restore_UI_Widget_Values.gui_restore_settings(self.ui, self.settings)
self.ui.closeEvent = self.closeEvent
self.ui.show()
def closeEvent(self, event):
PyQt4_Save_Restore_UI_Widget_Values.gui_save_settings(self.ui, self.settings)
window = app_conf()
#===================================================================
# 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
def gui_save_settings(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)
def gui_restore_settings(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
value = settings.value(name).toString()
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.toBool()) # restore checkbox
################################################################
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()
我的设置模块(PyQt4_Save_Restore_UI_Widget_Values.py)如下所示:
#import sip
#sip.setapi('QVariant', 2)
#sip.setapi('QString', 2)
import inspect
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
sys.path.append("C:\\Program Files (x86)\\QtiPlot\\app\\02 Python Packages")
import PyQt4_Save_Restore_UI_Widget_Values
class app_conf(QtGui.QWidget):
def __init__(self):
super(self.__class__, self).__init__()
self.version = 1.0
QtCore.QCoreApplication.setOrganizationName("Organization")
QtCore.QCoreApplication.setApplicationName("Application")
QtCore.QSettings.setPath(QSettings.IniFormat, QSettings.UserScope, "C:\\Program Files (x86)\\QtiPlot\\app\\02 Python Packages\\saved.ini")
self.settings = QtCore.QSettings("C:\\Program Files (x86)\\QtiPlot\\app\\02 Python Packages\\saved.ini", QSettings.IniFormat)
from PyQt4 import uic
self.ui = uic.loadUi(r"C:\Program Files (x86)/QtiPlot/app/03 UI Files/Config.ui")
PyQt4_Save_Restore_UI_Widget_Values.gui_restore_settings(self.ui, self.settings)
self.ui.closeEvent = self.closeEvent
self.ui.show()
def closeEvent(self, event):
PyQt4_Save_Restore_UI_Widget_Values.gui_save_settings(self.ui, self.settings)
window = app_conf()
#===================================================================
# 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
def gui_save_settings(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)
def gui_restore_settings(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
value = settings.value(name).toString()
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.toBool()) # restore checkbox
################################################################
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()
最好的解决方案是使用
sip.setapi
。但要使其正常工作,必须在应用程序中首次导入PyQt之前调用它。因此,它需要进入主脚本,而不是配置模块:
#===================================================================
# Module with functions to save & restore qt widget values
# Written by: Alan Lilly
# Website: http://panofish.net
#===================================================================
import sys
import sip
sip.setapi('QVariant', 2)
sip.setapi('QString', 2)
from PyQt4.QtCore import *
from PyQt4.QtGui import *
import inspect
这将确保
QVariant
和QString
始终自动转换为普通python类型-因此无需使用unicode()
、toString()
、toBool()
等。与Python2和SIP旧API一样,toString()
将返回QString
。对于get
和set
方法,必须使用str
将其强制为Python字符串。关于QCheckBox
,我使用了toInt
方法,而不是toBool
方法(这对我来说很好)
以下是保存和还原功能的修改版本:
def gui_save_settings(ui, settings):
for _, obj in inspect.getmembers(ui):
name = obj.objectName()
# Set QComboBox setting
if isinstance(obj, QComboBox):
value = str(obj.currentText()) # get current text from combobox
settings.setValue(name, value) # save combobox selection to registry
# Set QLineEdit setting
if isinstance(obj, QLineEdit):
value = str(obj.text())
settings.setValue(name, value) # save ui values, so they can be restored next time
# Set QCheckBox setting
if isinstance(obj, QCheckBox):
value = int(checkbox.isChecked())
settings.setValue(name, value)
def gui_restore_settings(ui, settings):
for _, obj in inspect.getmembers(ui):
name = obj.objectName()
# Get QComboBox setting
if isinstance(obj, QComboBox):
value = str(settings.value(name).toString())
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.addItem(value)
index = obj.findText(value)
obj.setCurrentIndex(index) # preselect a combobox value by index
continue
# Get QLineEdit setting
if isinstance(obj, QLineEdit):
value = str(settings.value(name).toString())
obj.setText(value) # restore lineEditFile
continue
# Get QCheckBox setting
if isinstance(obj, QCheckBox):
value, res = settings.value(key).toInt() # get stored value from registry
if res:
obj.setCheckState(value) # restore checkbox
continue
谢谢你的回答!恐怕我已经试过了。我在代码的开头添加了这些行(参见注释掉的行)。我还尝试只将上面显示的两个文件加载到QtiPlot应用程序中。似乎PyQt以前已经被调用过,我不知道如何重写这个行为。也许我应该考虑使用Python 3来代替?@马林。是的,它看起来像是qtiplot预加载了PyQt4,因此您不能在正确的时间调用
setapi
。切换到Python 3可以解决这个问题,因为默认情况下它使用v2 API。然而,您的qtiplot安装似乎必须根据Python2进行编译,否则我认为您在尝试加载脚本时会看到错误。如果是这样的话,您还需要一个与Python 3兼容的qtiplot版本。如果您无法切换到Python 3,请编辑您的问题并添加Config.ui
文件,以便其他人可以测试您的代码。谢谢您的回答!我知道我确实错过了一些东西。但是,当我尝试您的代码时,出现以下错误:语法错误:无效语法,对于行:value,res=settings.value(key).toInt())#从注册表获取存储值。为什么在这行中分配了两个参数?@Maryn根据toInt
返回一个元组。编辑:有一个额外的括号,我修正了。再次感谢!现在我没有任何错误,但仍然没有保存任何值。我使用一个INI文件,并在其中存储了一些默认值。只要我使用这个文件,默认值就会恢复。当我停止使用INI文件时,我再次只存储“PyQt4.QtCore.QVariant object at…”字符串。我怀疑这可能是因为我没有正确设置我的应用程序?这些值是否可以存储到当前配置中的INI文件中?因为我只从QtiPlot加载代码,所以是否需要QtGUI.QApplication分配(如“main”文件)?还有什么原因呢?@Maryn确实,我没有使用和你相同的构造函数。我使用QtCore.QSettings(“组织”、“应用程序”)
并让Qt处理目标设置文件。您可以尝试此构造函数,然后使用setDefaultFormat(Format Format)
ti指定您的文件格式。再次感谢!我试图使用您的构造函数,但这并没有改变所描述的行为。我的意思是,当我将你的构造函数与“QtCore.QSettings.Ini格式”一起使用时,那么这些值应该被写入一个Ini文件,对吗?我不应该在应用程序文件夹中找到此文件吗?因为我在那里看不到任何新文件,因此无法检查这些值是否存储在这样的文件中。我还是不明白为什么它不起作用。我想我赚了一点