QSettings介绍【转】
簡(jiǎn)介
QSettings類提供了持久的跨平臺(tái)應(yīng)用程序設(shè)置。
用戶通常期望應(yīng)用程序記住它的設(shè)置(窗口大小、位置等)所有會(huì)話。這些信息通常存儲(chǔ)在Windows系統(tǒng)注冊(cè)表,OS X和iOS的屬性列表文件中。在Unix系統(tǒng)中,在缺乏標(biāo)準(zhǔn)的情況下,許多應(yīng)用程序(包括KDE應(yīng)用程序)使用INI文本文件。
QSettings圍繞這些抽象技術(shù),使我們能夠以便攜的方式保存和恢復(fù)應(yīng)用程序設(shè)置。它還支持自定義存儲(chǔ)格式。
QSettings API基于QVariant,可以保存很多基礎(chǔ)的類型,比如 QString、QRect、QImage等。
如果你需要的是一個(gè)非持久性的基于內(nèi)存結(jié)構(gòu),可以考慮使用QMap<QString, QVariant>代替。
- 簡(jiǎn)介
- 基本用法
- QVariant和GUI類型
- 重點(diǎn)說明
- 后備機(jī)制
- 存儲(chǔ)GUI程序狀態(tài)
- 同時(shí)從多個(gè)線程或進(jìn)程訪問QSettings
- 特定平臺(tái)
- 應(yīng)用程序設(shè)置的存儲(chǔ)位置
- 訪問INI和plist文件
- 訪問Windows注冊(cè)表
- 訪問Windows上常見的注冊(cè)表設(shè)置
- 平臺(tái)限制
基本用法
當(dāng)創(chuàng)建一個(gè)QSettings對(duì)象時(shí),必須通過指定公司或組織名稱以及產(chǎn)品名稱,例如:公司名稱為:MySoft,產(chǎn)品名為:Star Runner,那么可以用下列方式來構(gòu)造QSettings對(duì)象:
QSettings settings("MySoft", "Star Runner");
QSettings對(duì)象既可以創(chuàng)建在棧上,也可以創(chuàng)建在堆(即使用new)上,構(gòu)建和銷毀也非常快。
如果你的應(yīng)用程序在很多地方使用QSettings,則可以使用QCoreApplication::setOrganizationName() 和 QCoreApplication::setApplicationName()來指定組織名和應(yīng)用名,然后使用默認(rèn)的QSettings構(gòu)造函數(shù):
QCoreApplication::setOrganizationName("MySoft"); QCoreApplication::setOrganizationDomain("mysoft.com"); QCoreApplication::setApplicationName("Star Runner"); ... QSettings settings;QSettings可以存儲(chǔ)一系列設(shè)置。每個(gè)設(shè)置包括指定設(shè)置名稱(鍵)的一個(gè)字符串和一個(gè)與該鍵關(guān)聯(lián)的QVariant存儲(chǔ)數(shù)據(jù)。使用setValue()可以實(shí)現(xiàn)一個(gè)設(shè)置。例如:
settings.setValue("editor/wrapMargin", 68);
如果存在相同的設(shè)置鍵,現(xiàn)有的值將被新值覆蓋。為了提高效率,這些變化可能不會(huì)被立即保存到永久存儲(chǔ)(可以隨時(shí)調(diào)用sync()來提交更改)。
可以使用value()得到一個(gè)設(shè)置的值:
int margin = settings.value("editor/wrapMargin").toInt();
如果沒有指定鍵對(duì)應(yīng)的設(shè)置,QSettings將會(huì)返回一個(gè)空QVariant(可轉(zhuǎn)換為整數(shù)0)。這時(shí),我們可以通過另一個(gè)參數(shù)來指定默認(rèn)值:
int margin = settings.value("editor/wrapMargin", 80).toInt();
- contains() 判斷一個(gè)指定的鍵是否存在
- remove() 刪除相關(guān)的鍵
- allKeys() 獲取所有鍵
- clear() 刪除所有鍵
void QSettings::beginGroup(const QString & prefix)
為當(dāng)前組附加前綴。
當(dāng)前組會(huì)自動(dòng)追加到指定QSettings所有鍵。此外,查詢功能,如childGroups()、childKeys()、allKeys() 也是基于組的。默認(rèn)情況下,不存在組設(shè)置。
組是有用的,以避免輸入同樣的設(shè)置路徑。例如:
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();這將生成三個(gè)設(shè)置值:
- mainwindow/size
- mainwindow/fullScreen
- outputpanel/visible
int QSettings::beginReadArray(const QString & prefix)
為當(dāng)前組添加前綴,并開始從數(shù)組中讀取。返回?cái)?shù)組的大小。
例:
void QSettings::beginWriteArray(const QString & prefix, int size = -1)
為當(dāng)前組添加前綴,并開始寫大小為size的數(shù)組。如果大小為-1(默認(rèn)值),系統(tǒng)會(huì)自動(dòng)根據(jù)索引的數(shù)目確定。
如果有許多出現(xiàn)一定的鍵集,可以使用數(shù)組實(shí)現(xiàn)更容易。例如,假設(shè)想要保存的用戶名和密碼的長度可變的列表。然后,你可以寫:
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();生成的結(jié)果如下:
- logins/size
- logins/1/userName
- logins/1/password
- logins/2/userName
- logins/2/password
- logins/3/userName
- logins/3/password
- …
enum QSettings::Format
這個(gè)枚舉類型指定QSettings所使用的存儲(chǔ)格式。
| QSettings::NativeFormat | 0 | 使用平臺(tái)最合適的存儲(chǔ)格式設(shè)置。在Windows中,使用系統(tǒng)注冊(cè)表;OS X和iOS中,使用的是CFPreferences API;在Unix中,使用的是INI格式的文本配置文件。 |
| QSettings::IniFormat | 1 | 存儲(chǔ)在INI文件中的設(shè)置。 |
| QSettings::InvalidFormat | 16 | registerFormat()返回的值 |
Unix中,NativeFor??mat和IniFormat意思是一樣的,只是文件擴(kuò)展名不同(NativeFor??mat為.conf,IniFormat 為.ini)。
enum QSettings::Scope
該枚舉指定設(shè)置是否用戶特定或同一系統(tǒng)的所有用戶共享。
| QSettings::UserScope | 0 | 在一個(gè)位置存儲(chǔ)特定于當(dāng)前用戶的設(shè)置(例如,用戶的主目錄)。 |
| QSettings::SystemScope | 1 | 在一個(gè)全局位置存儲(chǔ)設(shè)置,以便在相同機(jī)器上所有用戶訪問同一組的設(shè)置。 |
void QSettings::setPath(Format format, Scope scope, const QString & path)
為給定格式和范圍設(shè)置用來存儲(chǔ)的路徑。對(duì)于路徑而言,該格式可以是自定義格式。
下表總結(jié)了默認(rèn)值:
| Windows | IniFormat | 1.UserScope 2.SystemScope | 1.%APPDATA% 2.%COMMON_APPDATA% |
| Unix | NativeFormat, IniFormat | 1.UserScope 2.SystemScope | 1.$HOME/.config 2./etc/xdg |
| Qt for Embedded Linux | NativeFormat, IniFormat | 1.UserScope 2.SystemScope | 1.$HOME/Settings 2./etc/xdg |
| OS X and iOS | IniFormat | 1.UserScope 2.SystemScope | 1.$HOME/.config 2./etc/xdg |
在Windows、OS X、iOS中設(shè)置NativeFormat沒有任何效果。
警告:此功能不會(huì)影響現(xiàn)有QSettings對(duì)象。
QVariant和GUI類型
因?yàn)镼Variant是Qt Core模塊的一部分,它不能提供轉(zhuǎn)換功能到數(shù)據(jù)類型-例如:QColor、QImage、 QPixmap,因?yàn)檫@是Qt GUI的一部分。換句話說,QVariant中沒有toColor()、toImage()、toPixmap()等接口。
相反,可以使用QVariant::value()或qVariantValue()模板函數(shù)。 例如:
QSettings settings("MySoft", "Star Runner"); QColor color = settings.value("DataPump/bgcolor").value<QColor>();逆轉(zhuǎn)換(例如,從QColor到QVariant)是自動(dòng)通過QVariant支持的所有數(shù)據(jù)類型,包括GUI相關(guān)類型:
QSettings settings("MySoft", "Star Runner"); QColor color = palette().background().color(); settings.setValue("DataPump/bgcolor", color);自定義類型注冊(cè)使用qRegisterMetaType()和qRegisterMetaTypeStreamOperators()可以使用QSettings存儲(chǔ)。
重點(diǎn)說明
設(shè)置中的鍵可以包含任何Unicode字符。Windows注冊(cè)表和INI文件使用對(duì)鍵不區(qū)分大小寫,而在OS X和iOS的CFPreferences API使用區(qū)分大小寫。為了避免可移植性問題,需要遵循這些簡(jiǎn)單的規(guī)則:
可以使用’ / ‘字符作為分隔符形成分層鍵,類似于Unix文件路徑。例如:
settings.setValue("mainwindow/size", win->size()); settings.setValue("mainwindow/fullScreen", win->isFullScreen()); settings.setValue("outputpanel/visible", panel->isVisible());如果想保存或恢復(fù)具有相同前綴的一些設(shè)置,可以使用beginGroup()來指前綴,結(jié)束時(shí)調(diào)用endGroup()。下面和上面的例子相同,但這時(shí)使用組機(jī)制:
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();如果一個(gè)組使用beginGroup()設(shè)置,大多數(shù)功能的行為變化,組可以遞歸地設(shè)置。
后備機(jī)制
假設(shè)你用組織名MySoft、應(yīng)用名Star Runner創(chuàng)建了一個(gè)QSettings對(duì)象,當(dāng)查看一個(gè)值時(shí),依次搜索四個(gè)地方:
如果一個(gè)鍵不能在第一位置被找到時(shí),繼續(xù)在第二的位置搜索,依此類推。這確保能夠存儲(chǔ)系統(tǒng)范圍或組織范圍內(nèi)的設(shè)置,并在每個(gè)用戶或每個(gè)應(yīng)用程序覆蓋它們,使用setFallbacksEnabled(false)可以關(guān)閉這一機(jī)制。
雖然可以讀取來自所有四個(gè)位置的鍵,僅第一個(gè)文件(用戶特定的應(yīng)用程序)用于寫入訪問。要寫入任何其他文件,省去了程序名和指定QSettings:: SystemScope(相對(duì)于QSettings:: UserScope,默認(rèn)值)。
用一個(gè)例子看看:
QSettings obj1("MySoft", "Star Runner"); QSettings obj2("MySoft"); QSettings obj3(QSettings::SystemScope, "MySoft", "Star Runner"); QSettings obj4(QSettings::SystemScope, "MySoft");下表總結(jié)了QSettings對(duì)象訪問的位置。”X”表示該位置相關(guān)聯(lián)的QSettings對(duì)象的主要位置,既可以讀取也可以寫入,”O(jiān)”是指讀操作時(shí)被占用當(dāng)做后備。
| User, Application | X | ? | ? | ? |
| User, Organization | o | X | ? | ? |
| System, Application | o | ? | X | ? |
| System, Organization | o | o | o | X |
這種機(jī)制的優(yōu)點(diǎn)在于它可以在Qt支持的所有平臺(tái)運(yùn)行,它仍然給我們一個(gè)很大的靈活性,無需指定任何文件名或注冊(cè)表路徑。
如果想在所有平臺(tái)上不使用原生API來使用 INI文件,可以通過 QSettings::IniFormat格式作為QSettings構(gòu)造函數(shù)的第一個(gè)參數(shù),其次是范圍,組織名,以及應(yīng)用名:
QSettings settings(QSettings::IniFormat, QSettings::UserScope, "MySoft", "Star Runner");
可以參考:Settings Editor例子(可以體驗(yàn)不同的設(shè)置-回退、打開、關(guān)閉)。
存儲(chǔ)GUI程序狀態(tài)
QSettings通常用于存儲(chǔ)GUI程序的狀態(tài)。下面的例子演示了如何使用QSettings保存和恢復(fù)應(yīng)用程序的主窗口的幾何形狀。
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(); }可以參考: Window Geometry。為什么調(diào)用QWidget::resize()和QWidget::move()更好,而不是QWidget::setGeometry()來恢復(fù)窗口的幾何形狀。
必須在MainWindow構(gòu)造函數(shù)和關(guān)閉事件處理程序中調(diào)用readSettings()和writeSettings()函數(shù),如下:
MainWindow::MainWindow() {...readSettings(); }void MainWindow::closeEvent(QCloseEvent *event) {if (userReallyWantsToQuit()) {writeSettings();event->accept();} else {event->ignore();} }可以參考自帶的Application程序示例使用QSettings例子。
同時(shí)從多個(gè)線程或進(jìn)程訪問QSettings
QSettings是可重入的,意味著可以同時(shí)在不同的線程中使用不同的QSettings對(duì)象,這保證QSettings對(duì)象操作同一磁盤上的文件(或在系統(tǒng)注冊(cè)表中的相同條目)。如果通過QSettings對(duì)象修改了一個(gè)設(shè)置,那么對(duì)于操作在同一位置和存在相同的進(jìn)程的其他QSettings對(duì)象來說,更改會(huì)立即可見。
QSettings可以由不同的進(jìn)程(其可以是應(yīng)用程序同時(shí)運(yùn)行的不同實(shí)例或完全不同的應(yīng)用程序)安全地使用-在相同的系統(tǒng)位置上進(jìn)行讀寫,它使用勸告式文件鎖和智能合并算法以確保數(shù)據(jù)的完整性,需要注意的是sync()由其他進(jìn)程所做的更改。
特定平臺(tái)
應(yīng)用程序設(shè)置的存儲(chǔ)位置
如上所提到的,在后背機(jī)制部分,QSettings為應(yīng)用程序存儲(chǔ)的設(shè)置多達(dá)四個(gè)位置,這取決于設(shè)置是否是特定于用戶或系統(tǒng)范圍的,設(shè)置是否特定于應(yīng)用或組織范圍的。為簡(jiǎn)單起見,我們假設(shè)該組織被稱為MySoft并且應(yīng)用程序被稱為Star Runner。
在Unix系統(tǒng)中,如果文件格式是NativeFormat,默認(rèn)使用以下文件:
在Mac OS X版本10.2和10.3中,這些文件所使用的默認(rèn)值:
在Windows上,NativeFormat設(shè)置存儲(chǔ)在注冊(cè)表路徑如下:
如果文件格式是IniFormat,,以下文件用于在Unix、Mac OS X,、和iOS:
在Windows中,使用以下文件:
%APPDATA%路徑通常為:C:\Documents and Settings\All Users\Application Data
%COMMONAPPDATA%路徑通常為:C:\Documents and Settings\All Users\Application Data。
在黑莓手機(jī)只有一個(gè)文件。如果文件格式是IniFormat,這時(shí)”Settings/MySoft/Star Runner.ini”在應(yīng)用程序的主目錄。
對(duì)于在.ini和conf文件的路徑,可以使用的setPath()來改變。在Unix、Mac OS X、iOS中,用戶可以通過設(shè)置XDG_CONFIG_HOME環(huán)境變量替代他們。
訪問INI和.plist文件
有時(shí)候,想在一個(gè)特定的文件或注冊(cè)表路徑中訪問存儲(chǔ)設(shè)置。在所有平臺(tái)上,如果想直接讀取INI文件,可以使QSettings構(gòu)造函數(shù)的第一個(gè)參數(shù)為文件名,第二個(gè)參數(shù)為QSettings::IniFormat。例如:
QSettings settings("/home/petra/misc/myapp.ini", QSettings::IniFormat);
然后,就可以對(duì)文件進(jìn)行讀寫設(shè)置。
在OS X和iOS中,可以通過指定第二個(gè)參數(shù)為QSettings::NativeFormat訪問屬性列表的.plist文件。例如:
QSettings settings("/Users/petra/misc/myapp.plist", QSettings::NativeFormat);
訪問Windows注冊(cè)表
在Windows中,QSettings可以在系統(tǒng)注冊(cè)表訪問由QSettings寫入的設(shè)置(或設(shè)置支持的格式,如字符串?dāng)?shù)據(jù))。通過使用一個(gè)注冊(cè)表路徑和QSettings::NativeFormat來構(gòu)建一個(gè)QSettings對(duì)象。例如:
QSettings settings("HKEY_CURRENT_USER\\Software\\Microsoft\\Office", QSettings::NativeFormat);
所有出現(xiàn)在指定的路徑下的注冊(cè)表?xiàng)l目,可以通過QSettings對(duì)象像往常一樣進(jìn)行讀寫(使用斜杠而不是反斜杠)。例如:
settings.setValue("11.0/Outlook/Security/DontTrustInstalledFiles", 0);
注意,反斜線字符,如前所述,使用QSettings分割為子項(xiàng)。這樣一來,不能讀寫包含斜線或反斜線Windows注冊(cè)表項(xiàng),如果需要的話,應(yīng)該使用Windows API。
訪問Windows上常見的注冊(cè)表設(shè)置
在Windows上,有可能存在一個(gè)鍵既有值又存在子鍵。其默認(rèn)值是通過使用”Default”或”.” 來代替子鍵。
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"平臺(tái)限制
盡管QSettings試圖支持??不同平臺(tái),但還存在著一些差異,我們應(yīng)該知道,當(dāng)移植應(yīng)用程序:
Windows系統(tǒng)注冊(cè)表有以下限制:一個(gè)子項(xiàng)不能超過255個(gè)字符,一個(gè)條目的值不得超過16,383個(gè)字符,一個(gè)鍵的所有值不得超過65,535個(gè)字符。要解決這些局限性的一種方法是使用IniFormat代替NativeFor??mat存儲(chǔ)設(shè)置。
在OS X和iOS中,allKeys()將返回適用于所有應(yīng)用程序的全局設(shè)置一些額外的鍵。這些鍵可以使用value()讀取,但不能改變,只能跟蹤。調(diào)用setFallbacksEnabled(false) 將隱藏這些全局設(shè)置。
在OS X和iOS,使用QSettings的CFPreferences API預(yù)計(jì)互聯(lián)網(wǎng)域名而不是組織名。為了提供一個(gè)統(tǒng)一的API,QSettings源于該組織名提供一個(gè)假域??名(除非組織名已經(jīng)是一個(gè)域名,如:OpenOffice.org)。該算法追加”.com”到公司名,并用連字符替換空格和其他非法字符。如果你想指定不同的域名,在main()函數(shù)中調(diào)用QCoreApplication::setOrganizationDomain()、QCoreApplication::setOrganizationName()、QCoreApplication::setApplicationName(),然后使用默認(rèn)的QSettings構(gòu)造函數(shù)。
另一種解決方案是使用預(yù)處理指令,例如:
原文作者:一去丶二三里 作者博客:去作者博客空間
總結(jié)
以上是生活随笔為你收集整理的QSettings介绍【转】的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Vista优化大师更新历史:
- 下一篇: 树形选择变成表格树选择