使用python 2.7.6 / PyQt4处理设置模块中的QVariants

时间:2016-09-17 18:42:36

标签: python pyqt4

我之前已阅读过本网站和其他平台上的几个主题,但我的代码仍无法正常工作。我似乎无法将所有拼图拼凑在一起,需要有人查看我的代码。

我正在为程序QtiPlot编写插件。我使用Python 2.7.6和PyQt4。我用QT Designer创建了Plugin GUI。我也是Python的新手。我正在使用这些" old"资源,因为我的前任已经使用过它们。

我目前的任务是开发设置,即能够保存和恢复参数。 为此,我在此网站上找到了一个模板:Python PyQt4 functions to save and restore UI widget values?

我想将参数保存到Ini-File。 但是我对QVariants有问题。而不是我插入插件中的字符串,表达式" PyQt4.QtCore.QVariant对象位于0x08667FB0"正在得救。我已经知道这是一个问题,因为QVariant没有被正确地转换回Python对象。

因此,为了手动转换QVariants,我添加了短语" toString()"恢复功能中QLineEdit-Objects的值赋值(注释掉的行是以前的版本)。但是我的插件中的QLineEdit-Blocks是空的,这让我很困惑。我在文档中读到如果QVariant不包含其中一种预设类型(包括字符串),则返回空字符串。但是这种情况发生了,尽管我之前输入了一个字符串。

这是否意味着首先没有正确保存字符串?或者它是什么意思,我想念什么或我做错了什么?

我还注意到Ini-File中没有存储任何值,因此部分代码仍然存在错误。但我不确定这是否是由于保存功能不起作用或因为Ini结构本身是错误的。

此外,我尝试在配置文件的头部使用SIP模块来解决我的问题(它也被注释掉了,因为到目前为止它对我来说并不起作用)。但是,虽然我把它放在代码的头部,然后我得到错误" API' QVariant'已经设置为版本1"。我不明白为什么或从SIP指令被覆盖的内容。有什么方法可以解决这个问题吗?

我的配置程序如下所示:

#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()

我的设置模块(PyQt4_Save_Restore_UI_Widget_Values.py)如下所示:

#===================================================================
# 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() 

2 个答案:

答案 0 :(得分:2)

与Python 2和SIP旧API一样,toString()将返回QString。对于strget方法,您必须使用set将其强制为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

答案 1 :(得分:1)

最佳解决方案是使用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

这将确保QVariantQString始终自动转换为普通的python类型 - 因此无需使用unicode()toString()toBool()