qt QSettings 用法总结

用户对应用程序经常有这样的要求:要求它能记住它的settings,比如窗口大小,位置,一些别的设置,还有一个经常用的,就是recent files,等等这些都可以通过Qsettings来实现。
我们知道,这些settings一般都是存在系统里的,比如windows一般都写在系统注册表或者写INI文件,mac系统一般都在XML文件里,那么按照一般的标准来说,许多应用程序是用INI文件来实现的。而Qsettings就是提供了一种方便的方法来存储和恢复应用程序的settings。
QSettings的API是基于Qvariant,Qvariant是一种数据类型的集合,它包含了大部分通常的Qt数据类型,比如QString,QRec,QImage,等等。
当我们创建一个Qsettings的对象时,我们需要传递给它两个参数,第一个是你公司或者组织的名称,第二个事你的应用程序的名称。比如:
Settings = Qsettings(“MySoft”,”QtPad”)
公司名称:MySoft,程序名称:QtPad
假如我们在应用程序中多次要用到Qsettings,为了简单其间,我们可以在主程序中先如下声明。
QtCore.QCoreApplication.setOrganizationName(“MySoft”)
QtCore.QCoreApplication.setOrganizationDomain(“mysoft.com”)
QtCore.QCoreApplication.setApplicationName(“QtPad”)
当然前提是已经from PyQt4 import QtCore
然后在应用程序的任何地方想要声明一个Qsettings类型的变量,便不需要书写两个参数了,直接用settings = Qsettings即可。
那么如何用它来保持应用程序的settings信息呢?我们以字典数据类型与之类比,它也有key,以及对应的value。比如下面例子:
settings = Qsettings(“MySoft”,”QtPad”)
Mainwindow = QmainWindow()
settings.setValue(“pos”,QVariant(Mainwindow.pos())
settings.setValue(“size”,QVariant(Mainwindow.size())
上面两句就是把当前窗口的位置,和大小两个信息记录到了settings中,其中的key就是”pos”和”size”两个Qstring类型,而它所对应的值就是QVariant类型的。当然如果我们要写的key已在settings中存在的话,则会覆盖原来的值,写入新值。
如何读取Qsettings里的内容呢?如下:
Pos = settngs.value(“pos”).toPoint()
Size = settings.value(“size”).toSize()
当然如果key所对应的value是int型的,也可toInt(),如果没有我们要找的key,则会返回一个null QVariant如果用toInt的话会得到0。
那么实际应用中我们一般会如下:
pos= settings.value(“pos”, QVariant(QPoint(200, 200))).toPoint()
size= settings.value(“size”, QVariant(QSize(400, 400))).toSize()
self.resize(size)
self.move(pos)
意思是,如果settings里有以前存下的(用setValue设置的)pos和size的值,则读取,如果没有,不会返回null,而会使用我们给它的起始值——default value——即应用程序第一次运行时的情况。

注意:因为QVariant是不会提供所有数据类型的转化的,比如有toInt(),toPoint(),toSize(),但是却没有对Qcolor,Qimage和Qpixmap等数据类型的转化,此时我们可以用QVariant.value(),具体参看QVariant模块说明。
下面看看如何在应用程序中使用:
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
class MainWindow(QMainWindow):
def init(self):
QMainWindow.init(self)

self.readSettings()

def readSettings(self):
settings = Qsettings(“MySoft”,”QtPad”)
pos=settings.value(“pos”,QVariant(QPoint(200,200))).toPoint()
size=settings.value(“size”,QVariant(QSize(400,400))).toSize()
self.resize(size)
self.move(pos)
def writeSettings(self):
settings = Qsettings(“MySoft”,”QtPad”)
settings.setValue(“pos”, QVariant(self.pos()))
settings.setValue(“size”, QVariant(self.size()))
def closeEvent(self,event):
if self.maybeSave():
self.writeSettings()
event.accept()
else:
event.ignore()
上面是一般应用程序的应用方法。

下面再看一些Qsettings里常用的metho:
Qsettings.annKeys(self)返回所有的key,以list的形式
Qsettings.applicationName(self)返回应用程序名称
Qsettings.clear(self) 清楚此settings里的内容
Bool Qsettings.contains(self,key)返回真,如果存在名为key的key
Qsettings.remove(self, keyname)清楚key及其所对应的value
Qsetting.fileName() 返回写入注册表地址,或者INI文件路径
等等,请参看帮助文档。

我们可以探索一下,这些settings在应用程序关闭以后到底存到了什么地方呢?
我们可以在上面的程序中的writeSettings中,后面加一句话:
Print Settings.fileName()
这个在windows下,默认Qsettings会打印出这个程序的系统注册表所在地:
这个结果是:HKEY_CURRENT_USERSoftwareMySoftQtPad

由此我们可以看出,这个writesettings其实就是个写注册表的过程。
当然,我们也可以不写注册表,我们写ini文件:
settings = QSettings(“./QtPad.ini”, QSettings.IniFormat)
settings.setValue(“pos”, QVariant(self.pos()))
settings.setValue(“size”, QVariant(self.size()))
就会在当前文件夹下产生一个QtPad.ini文件,打开后文件内容为:
[General]
pos=@Point(200 200)
size=@Size(400 400)

更多关于Qsettings内容请参考帮助文档

QSettings用了一下,确实简单易懂~

:5_118: 我还有很多不明白....

今天看了很好的帖子,转过来一起学习~~~
URL:http://blog.csdn.net/aizhaoyu/article/details/11527147
QSetting是一个平台无关的可以设置和读取应用程序设置的类用户可能希望应用程序记住自己应用程序的设置,windows记录在注册表中,mac中记录在xml中,在unix中,缺乏标准,所以很多都记录在.ini文本文件中QSetting的API都是基于QVariant的,允许保存很多类型的数据,例如QString,QRect,和QImage
基本用法:当创建一个QSetting对象时候,应该把公司或组织,还有应用程序的名字传递给构造函数,例如,如果应用程序叫做Star Runner,公司叫做MySoft,那么应该像下面这样构造对象QSetting settings(“MySoft”,”Star Runner”);QSetting的对象可以再堆或者栈上创建,构造和析构都非常快如果在应用程序你在很多地方用QSetting,可以使用QCoreApplication::setOrganizationName()和QCoreApplication::setApplicationName()设置组织名和应用程序,然后使用QSetting的默认构造函数
QCoreApplication::setOrganizationName(“MySoft”);

 QCoreApplication::setOrganizationDomain("mysoft.com");

QCoreApplication::setApplicationName("Star Runner");

 ...

 QSettings settings;

这里我们也指定了组织的网络域名,使用QCoreApplication::setOrganizationDomain()
QSetting有键和值组成,使用QString指定键key的名字,使用QVariant来存储和key相关联的值,设定key,使用setValue(),例如Setting.setValue(“editor/warpMargin”,68);如果已经存在了同名的key,那么新的值会覆盖原来的值获取setting的值使用value()函数Intmargin=setting.value(“editor/warpMargin”).toInt();如果没有指定的key,那么value()会返回一个Null QVariant,也可以为value()指定一个缺省的值,如下面Intmargin=setting.value(“editor/warpMargin,80).toInt();缺省值就是80,value()返回的值是一个QVariant,把他转换成int类型
QVariant和GUI类型因为QVariant是QtCore库的一部分,不能提供一个方便的函数转换成QColor,QImage和QPixmap,因为这些是QtGui的一部分,换句话说,没有toColor(),toImage(),toPixmap()等方法,但是我们可以使用qVariantValue()模板函数或者QVariant::value来转换,他们是等价的,例如

QSettings settings("MySoft", "Star Runner");
QColor color = settings.value("DataPump/bgcolor").value<QColor>();

相反的转换过程是QVariant自动支持的,包括GUI相关类型,例如

QSettings settings("MySoft", "Star Runner"); 
QColor color = palette().background().color(); 
settings.setValue("DataPump/bgcolor", color);

QSetting语法无论windows还是unix,使用“/”作为分隔符,而不是“\”,如果在一个地方指定了“text fonts”,就不要再其他地方指定“Text Fonts”,例如

 settings.setValue("mainwindow/size", win->size()); 
settings.setValue("mainwindow/fullScreen", win->isFullScreen());     
settings.setValue("outputpanel/visible", panel->isVisible());
如果想设置子目录,也可以使用beginGroup()和endGroup()配合使用,如下 
settings.beginGroup("mainwindow");     
settings.setValue("size", win->size());     
settings.setValue("fullScreen", win->isFullScreen());     
settings.endGroup();      
settings.beginGroup("outputpanel");  
settings.setValue("visible", panel->isVisible()); 
settings.endGroup();
效果和上面的一样除了group之外,QSetting也支持array概念,详见beginReadArray()和beginWriteArray如果有很多东西需要记录在setting中,可以使用arrays更简单一些,例如,你想保存一个变长的list,list中保存用户的name和password,可以用下面的代码
struct Login { 
QString userName;     
QString password; 
}; 
QList<Login> logins; 
... QSettings settings; 
settings.beginWriteArray("logins"); 
for (int i = 0; i < logins.size(); ++i) 
{ 
 settings.setArrayIndex(i); 
 settings.setValue("userName", list.at(i).userName); 
 settings.setValue("password", list.at(i).password); 
} 
settings.endArray();

得到的键如下[list]
[]logins/size
[
]logins/1/userName
[]logins/1/password
[
]logins/2/userName
[]logins/2/password
[
]logins/3/userName
[*]logins/3/password
[/list]其中size是自动侦测到的长度要想把他们读取出来,可以使用如下的方法

struct Login 
{ 
 QString userName;     
 QString password; 
};
 QList<Login> logins;
 ... QSettings settings; 
int size = settings.beginReadArray("logins"); 
for (int i = 0; i < size; ++i) 
{
 settings.setArrayIndex(i);     
 Login login; 
 login.userName = settings.value("userName").toString(); 
 login.password = settings.value("password").toString(); 
 logins.append(login); 
} 
settings.endArray();

例子, 保存GUI应用程序的状态在关闭应用程序时候保存应用程序窗口的大小和位置,在再次打开应用程序时候,读取出来

void MainWindow::writeSettings() 
{     
QSettings settings("Moose Soft", "Clipper");  
settings.beginGroup("MainWindow");     
settings.setValue("size", size());     
settings.setValue("pos", pos()); 
 settings.endGroup(); 
}
void MainWindow::readSettings() 
{ 
 QSettings settings("Moose Soft", "Clipper");      
 settings.beginGroup("MainWindow"); 
 resize(settings.value("size", QSize(400, 400)).toSize());     
move(settings.value("pos", QPoint(200, 200)).toPoint());     
settings.endGroup(); 
}

使用QWidget::resize()和QWidget::move()比QWidget::setGeometry()要更好在构造函数中调用readSetting(),在关闭窗口事件中调用writeSettings()MainWindow::MainWindow() { … readSettings(); } void MainWindow::closeEvent(QCloseEvent *event) { if (userReallyWantsToQuit()) { writeSettings(); event->accept(); } else { event->ignore(); } }

在多线程和多进程中使用QSettingQSetting是可重入的,意味着可以在不同的线程中使用不同的QSetting对象,这保证即便多个QSetting对象同时操作同一个文件或者磁盘,如果其中一个对象修改了文件或者注册表,同一个进程中其他操作同一个位置的QSetting对象能够检测到,并且不会读取到脏数据。在不同的进程中使用QSetting来读写同一个setting文件是安全的,它使用文件锁和智能合并算法来保证数据的完整,在sync()调用之前,这个进程中的修改在另一个进程中是不可见的, QSetting::sync()的作用是将那些未保存的修改永久写进存储中,并且在其他进程中重新载入这些修改的设置,这个函数被QSetting的析构函数自动调用,也被事件循环定期调用,一般情况下不需要手动调用。
应用程序settings保存的位置这里使用MySoft作为组织名,使用Star Runner作为应用程序名在unix系统上,如果文件格式是NativeFormat,默认使用下面的文件1 、$HOME/.config/MySoft/StarRunner.conf (Qt for Embedded Linux: $HOME/Settings/MySoft/Star Runner.conf)2、$HOME/.config/MySoft.conf(Qt for Embedded Linux: $HOME/Settings/MySoft.conf)3、/etc/xdg/MySoft/StarRunner.conf4、/etc/xdg/MySoft.conf
Mac os x上,默认使用下面的文件[list=1]
[]$HOME/Library/Preferences/com.MySoft.Star Runner.plist
[
]$HOME/Library/Preferences/com.MySoft.plist
[]/Library/Preferences/com.MySoft.Star Runner.plist
[
]/Library/Preferences/com.MySoft.plist
[/list]Windows上,NativeFormat设置被存储在下面路径的注册表中[list=1]
[]HKEY_CURRENT_USER\Software\MySoft\Star Runner
[
]HKEY_CURRENT_USER\Software\MySoft
[]HKEY_LOCAL_MACHINE\Software\MySoft\Star Runner
[
]HKEY_LOCAL_MACHINE\Software\MySoft
[/list]在windows上,32位程序运行在WOW64模式下,setting被存储在 HKEY_LOCAL_MACHINE\Software\WOW6432node.上如果是使用IniFormat,存储位置如下Mac OS X上[list=1]
[]$HOME/.config/MySoft/Star Runner.ini (Qt for Embedded Linux: $HOME/Settings/MySoft/Star Runner.ini)
[
]$HOME/.config/MySoft.ini (Qt for Embedded Linux: $HOME/Settings/MySoft.ini)
[]/etc/xdg/MySoft/Star Runner.ini
[
]/etc/xdg/MySoft.ini
[/list]Windows上[list=1]
[]%APPDATA%\MySoft\Star Runner.ini
[
]%APPDATA%\MySoft.ini
[]%COMMON_APPDATA%\MySoft\Star Runner.ini
[
]%COMMON_APPDATA%\MySoft.ini
[/list]%APPDATA%通常是 C:\Documents and Settings[i]User Name[/i]\ApplicationData;%COMMON_APPDATA% 通常是C:\Documents and Settings\All Users\Application Data.ini和.conf文件的路径可以使用setPath()来修改,在Mac OS X上,可以使用环境变量XDG_CONFIG_HOME直接读取INI和.plist文件在所有平台上,如果想直接读取ini文件,可以在QSetting的构造函数中,将ini文件的名和QSetting::IniFormat作为参数,如下QSettings settings(“/home/petra/misc/myapp.ini”, QSettings::IniFormat);
然后可以使用settings对象来读写这些设置在Mac OS X上,读取XML基础文件.plist通过传递参数QSetting::NativaFormat作为第二个参数,例如QSettings settings(“/Users/petra/misc/myapp.plist”, QSettings::NativeFormat);
直接读取Windows注册表通过传递给构造函数第二个参数QSetting::NativaFormat,第一个参数是注册表的键值位置,如下QSettings settings(“HKEY_CURRENT_USER\Software\Microsoft\Office”, QSettings::NativeFormat);
指定的路径下的所有注册表入口都可以通过QSetting像平常一样读写,例如settings.setValue(“11.0/Outlook/Security/DontTrustInstalledFiles”, 0);
在windows上,一个键可能有一个值和一个子键,他默认的值可以通过“Dafault”和“.”获取settings.setValue(“HKEY_CURRENT_USER\MySoft\Star Runner\Galaxy”, “Milkyway”); settings.setValue(“HKEY_CURRENT_USER\MySoft\Star Runner\Galaxy\Sun”, “OurStar”); settings.value(“HKEY_CURRENT_USER\MySoft\Star Runner\Galaxy\Default”); // returns “Milkyway”
在其他非windows平台上,“Default”和“.”将会被当做一般子键看待处理。

:7_143:这是个大好人呀

怎么将setting 文件写到指定目录

参见:http://www.ubuntukylin.com/ukylin/forum.php?mod=viewthread&tid=5110

在sync()调用之前,这个进程中的修改在另一个进程中是不可见的, QSetting::sync()的作用是将那些未保存的修改永久写进存储中,并且在其他进程中重新载入这些修改的设置,这个函数被QSetting的析构函数自动调用,也被事件循环定期调用,一般情况下不需要手动调用

今天就遇到了这个问题...郁闷了好久:3_58: