QSettings Class
QSettings类提供与平台无关的持久性应用程序设置。
Header: | #include <QSettings> |
qmake: | QT += core |
Inherits: | QObject |
注意:此类中的所有函数都是可重入的。
注意:这些函数也是线程安全的。
Public Types:
enum | Format { NativeFormat, Registry32Format, Registry64Format, IniFormat, InvalidFormat } |
typedef | ReadFunc |
enum | Scope { UserScope, SystemScope } |
typedef | SettingsMap |
enum | Status { NoError, AccessError, FormatError } |
typedef | WriteFunc |
Public Functions:
QSettings(QSettings::Scope scope, QObject *parent = nullptr) | |
QSettings(QObject *parent = nullptr) | |
QSettings(const QString &fileName, QSettings::Format format, QObject *parent = nullptr) | |
QSettings(QSettings::Format format, QSettings::Scope scope, const QString &organization, const QString &application = QString(), QObject *parent = nullptr) | |
QSettings(QSettings::Scope scope, const QString &organization, const QString &application = QString(), QObject *parent = nullptr) | |
QSettings(const QString &organization, const QString &application = QString(), QObject *parent = nullptr) | |
virtual | ~QSettings() |
QStringList | allKeys() const |
QString | applicationName() const |
void | beginGroup(const QString &prefix) |
int | beginReadArray(const QString &prefix) |
void | beginWriteArray(const QString &prefix, int size = -1) |
QStringList | childGroups() const |
QStringList | childKeys() const |
void | clear() |
bool | contains(const QString &key) const |
void | endArray() |
void | endGroup() |
bool | fallbacksEnabled() const |
QString | fileName() const |
QSettings::Format | format() const |
QString | group() const |
QTextCodec * | iniCodec() const |
bool | isAtomicSyncRequired() const |
bool | isWritable() const |
QString | organizationName() const |
void | remove(const QString &key) |
QSettings::Scope | scope() const |
void | setArrayIndex(int i) |
void | setAtomicSyncRequired(bool enable) |
void | setFallbacksEnabled(bool b) |
void | setIniCodec(QTextCodec *codec) |
void | setIniCodec(const char *codecName) |
void | setValue(const QString &key, const QVariant &value) |
QSettings::Status | status() const |
void | sync() |
QVariant | value(const QString &key, const QVariant &defaultValue = QVariant()) const |
Static Public Members
QSettings::Format | defaultFormat() |
QSettings::Format | registerFormat(const QString &extension, QSettings::ReadFunc readFunc, QSettings::WriteFunc writeFunc, Qt::CaseSensitivity caseSensitivity = Qt::CaseSensitive) |
void | setDefaultFormat(QSettings::Format format) |
void | setPath(QSettings::Format format, QSettings::Scope scope, const QString &path) |
Reimplemented Protected Functions保护方法
virtual bool event(QEvent *event) override
详细说明:
用户通常希望应用程序在会话之间记住其设置(窗口大小和位置、选项等)。这些信息通常存储在Windows的系统注册表中,以及macOS和iOS的属性列表文件中。在Unix系统上,在没有标准的情况下,许多应用程序(包括KDE应用程序)使用INI文本文件。
QSettings是围绕这些技术的抽象,使您能够以可移植的方式保存和恢复应用程序设置。它还支持自定义存储格式。
QSettings的API基于QVariant,使您可以省力地保存大多数基于值的类型,例如QString,QRect和QImage。
如果您需要的只是一个基于非持久性内存的结构,请考虑改用QMap <QString,QVariant>。
基本用法
创建QSettings对象时,必须传递公司或组织的名称以及应用程序的名称。例如,如果您的产品名为Star Runner,而您的公司名为MySoft,则您将按如下方式构造QSettings对象:
QSettings settings("MySoft", "Star Runner");
QSettings对象可以在堆栈或堆上创建(即使用new)。构造和销毁QSettings对象非常快。
如果您从应用程序中的许多地方使用QSettings,则可能要使用QCoreApplication :: setOrganizationName()和QCoreApplication :: setApplicationName()来指定组织名称和应用程序名称,然后使用默认的QSettings构造函数:
QCoreApplication::setOrganizationName("MySoft");
QCoreApplication::setOrganizationDomain("mysoft.com");
QCoreApplication::setApplicationName("Star Runner");
...
QSettings settings;
(在这里,我们还指定了组织的Internet域。当设置了Internet域时,它将用于macOS和iOS,而不是组织名称,因为macOS和iOS应用程序通常使用Internet域来标识自己。如果未设置域,则从组织名称派生一个伪域。有关详细信息,请参见下面的平台特定说明。)
QSettings存储设置。 每个设置都由一个QString和一个QVariant组成,该QString指定设置的名称(键),该QVariant存储与该键关联的数据。 要编写设置,请使用setValue()。 例如:
settings.setValue("editor/wrapMargin", 68);
如果已经存在具有相同键的设置,则现有值将被新值覆盖。 为了提高效率,更改可能不会立即保存到永久存储中。 (您始终可以调用sync()提交更改。)
您可以使用value()返回设置的值:
int margin = settings.value("editor/wrapMargin").toInt();
如果没有具有指定名称的设置,则QSettings返回一个空QVariant(可以将其转换为整数0)。 您可以通过将第二个参数传递给value()来指定另一个默认值:
int margin = settings.value("editor/wrapMargin", 80).toInt();
要测试给定密钥是否存在,请调用contains()。 要删除与键关联的设置,请调用remove()。 要获取所有键的列表,请调用allKeys()。 要删除所有键,请调用clear()。
QVariant和GUI类型
由于QVariant是Qt Core模块的一部分,因此它无法提供对Qt GUI的一部分的数据类型(例如QColor,QImage和QPixmap)的转换功能。 换句话说,在QVariant中没有toColor(),toImage()或toPixmap()函数。
相反,您可以使用QVariant :: value()模板函数。 例如:
QSettings settings("MySoft", "Star Runner");
QColor color = settings.value("DataPump/bgcolor").value<QColor>();
对于QVariant支持的所有数据类型,包括与GUI相关的类型,将自动进行逆转换(例如,从QColor到QVariant):
QSettings settings("MySoft", "Star Runner");
QColor color = palette().background().color();
settings.setValue("DataPump/bgcolor", color);
可以使用QSettings存储使用qRegisterMetaType()和qRegisterMetaTypeStreamOperators()注册的自定义类型。
Section and Key语法:键值和内容语法
设置键可以包含任何Unicode字符。 Windows注册表和INI文件使用不区分大小写的键,而macOS和iOS上的CFPreferences API使用不区分大小写的键。 为避免可移植性问题,请遵循以下简单规则:
- 总是使用相同的情况引用相同的密钥。
- 避免使用除大小写外相同的键名。
- 不要在节名或键名中使用斜杠(“/”和“\”);反斜杠字符用于分隔子键(见下文)。在windows上,“\”由QSettings转换为“/”,这使它们相同。
您可以使用'/'字符作为分隔符来形成分层键,类似于Unix文件路径。 例如:
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();
如果使用beginGroup()设置了一个组,则大多数函数的行为都会改变。 可以递归设置组。
除组外,QSettings还支持“数组”概念。 有关详细信息,请参见beginReadArray()和beginWriteArray()。
后备机制
假设您已经创建了一个QSettings对象,其组织名称为MySoft,应用程序名称为Star Runner。查找值时,将按此顺序搜索最多四个位置:
- Star Runner应用程序的用户特定位置
- MySoft所有应用程序的用户特定位置
- Star Runner应用程序在系统范围内的位置
- MySoft在所有应用程序的系统范围内的位置
(有关Qt支持的不同平台上这些位置的信息,请参阅下面的特定于平台的说明。)
如果在第一个位置找不到密钥,则在第二个位置继续搜索,依此类推。 这使您可以存储系统范围或组织范围的设置,并可以基于每个用户或每个应用程序覆盖它们。 要关闭此机制,请调用setFallbacksEnabled(false)。
尽管可以从所有四个位置读取密钥,但是只能访问第一个文件(应用程序的用户特定位置)进行写入。 要写入任何其他文件,请省略应用程序名称 and/or 指定QSettings :: SystemScope(与默认设置QSettings :: UserScope相对)。
让我们看一个例子:
QSettings obj1("MySoft", "Star Runner");
QSettings obj2("MySoft");
QSettings obj3(QSettings::SystemScope, "MySoft", "Star Runner");
QSettings obj4(QSettings::SystemScope, "MySoft");
下表总结了哪些QSettings对象访问哪个位置。 “ X”表示该位置是与QSettings对象关联的主要位置,并且用于读取和写入。 “ o”表示该位置在读取时用作备用。
Locations | obj1 |
obj2 |
obj3 |
obj4 |
---|---|---|---|---|
1. User, Application | X | |||
2. User, Organization | o | X | ||
3. System, Application | o | X | ||
4. System, Organization | o | o | o | X |
这种机制的优点在于,它可以在Qt支持的所有平台上运行,并且仍然为您提供了很大的灵活性,而无需您指定任何文件名或注册表路径。
如果要在所有平台上使用INI文件而不是本机API,则可以将QSettings :: IniFormat作为第一个参数传递给QSettings构造函数,然后是范围,组织名称和应用程序名称:
QSettings settings(QSettings::IniFormat, QSettings::UserScope,
"MySoft", "Star Runner");
请注意,从INI文件读取设置时不会保留类型信息。 所有值将作为QString返回。
设置编辑器示例可让您尝试不同的设置位置,以及启用或禁用后备机制。
恢复GUI应用程序的状态
QSettings通常用于存储GUI应用程序的状态。 下面的示例说明如何使用QSettings保存和还原应用程序主窗口的几何信息。
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()来恢复窗口几何的讨论,请参见窗口几何:Window Geometry 。
必须从主窗口的构造函数和close事件处理程序中调用readSettings()和writeSettings()函数,如下所示:
MainWindow::MainWindow()
{
...
readSettings();
}
void MainWindow::closeEvent(QCloseEvent *event)
{
if (userReallyWantsToQuit()) {
writeSettings();
event->accept();
} else {
event->ignore();
}
}
有关使用QSettings的独立示例,请参见“应用程序”示例。
同时从多个线程或进程访问设置
QSettings是可重入的。 这意味着您可以同时在不同的线程中使用不同的QSettings对象。 即使QSettings对象引用磁盘上的相同文件(或系统注册表中的相同条目),该保证仍然有效。 如果通过一个QSettings对象修改了设置,则该更改将立即在任何在同一位置运行且处于同一进程中的其他QSettings对象中可见。
如果满足某些条件,可以从不同的进程(可以是同时运行的应用程序的不同实例,也可以是不同的应用程序)安全地使用QSettings来读写相同的系统位置。 对于QSettings :: IniFormat,它使用咨询文件锁定和智能合并算法来确保数据完整性。 工作的条件是可写配置文件必须是常规文件,并且必须位于当前用户可以在其中创建新的临时文件的目录中。如果不是这种情况,则必须使用setAtomicSyncRequired() 关闭安全装置。
请注意,sync()导入其他进程所做的更改(除了从此QSettings中写入更改之外)。
平台特定说明
应用程序设置的存储位置
如“后备机制”部分所述,QSettings会将应用程序的设置最多存储在四个位置,具体取决于设置是用户特定的还是系统范围的,以及设置是特定于应用程序的还是组织范围的。 为了简单起见,我们假设该组织称为MySoft,而该应用程序称为Star Runner。
在Unix系统上,如果文件格式为NativeFormat,则默认使用以下文件:
$HOME/.config/MySoft/Star Runner.conf
(Qt for Embedded Linux:$HOME/Settings/MySoft/Star Runner.conf
)$HOME/.config/MySoft.conf
(Qt for Embedded Linux:$HOME/Settings/MySoft.conf
)- for each directory <dir> in $XDG_CONFIG_DIRS:
<dir>/MySoft/Star Runner.conf
- for each directory <dir> in $XDG_CONFIG_DIRS:
<dir>/MySoft.conf
注意:如果未设置XDG_CONFIG_DIRS,则使用/ etc / xdg的默认值。
在macOS版本10.2和10.3上,默认情况下使用以下文件:
$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
在Windows上,NativeFormat设置存储在以下注册表路径中:
HKEY_CURRENT_USER\Software\MySoft\Star Runner
HKEY_CURRENT_USER\Software\MySoft\OrganizationDefaults
HKEY_LOCAL_MACHINE\Software\MySoft\Star Runner
HKEY_LOCAL_MACHINE\Software\MySoft\OrganizationDefaults
注意:在Windows上,对于以WOW64模式运行的32位程序,设置存储在以下注册表路径中:HKEY_LOCAL_MACHINE \ Software \ WOW6432node。
如果文件格式为NativeFormat,则在应用程序的主目录中为“ Settings / MySoft / Star Runner.conf”。
如果文件格式为IniFormat,则在Unix,macOS和iOS上使用以下文件:
$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
)- for each directory <dir> in $XDG_CONFIG_DIRS:
<dir>/MySoft/Star Runner.ini
- for each directory <dir> in $XDG_CONFIG_DIRS:
<dir>/MySoft.ini
注意:如果未设置XDG_CONFIG_DIRS,则使用/ etc / xdg的默认值。
在Windows上,使用以下文件:
FOLDERID_RoamingAppData\MySoft\Star Runner.ini
FOLDERID_RoamingAppData\MySoft.ini
FOLDERID_ProgramData\MySoft\Star Runner.ini
FOLDERID_ProgramData\MySoft.ini
以FOLDERID_为前缀的标识符是特殊项目ID列表,将传递给Win32 API函数SHGetKnownFolderPath()以获得相应的路径。
FOLDERID_RoamingAppData通常指向C:\ Users \ User Name \ AppData \ Roaming,也由环境变量%APPDATA%显示。
FOLDERID_ProgramData通常指向C:\ ProgramData。
如果文件格式为IniFormat,则在应用程序的主目录中为“ Settings / MySoft / Star Runner.ini”。
.ini和.conf文件的路径可以使用setPath()进行更改。 在Unix,macOS和iOS上,用户可以通过设置XDG_CONFIG_HOME环境变量来覆盖它们。 有关详细信息,请参见setPath()。
直接访问INI和.plist文件
有时您确实想访问存储在特定文件或注册表路径中的设置。 在所有平台上,如果要直接读取INI文件,则可以使用QSettings构造函数,该构造函数以文件名作为第一个参数,并传递QSettings :: IniFormat作为第二个参数。 例如:
QSettings settings("/home/petra/misc/myapp.ini",
QSettings::IniFormat);
然后,您可以使用QSettings对象读取和写入文件中的设置。
在macOS和iOS上,您可以通过传递QSettings :: NativeFormat作为第二个参数来访问属性列表.plist文件。 例如:
QSettings settings("/Users/petra/misc/myapp.plist",
QSettings::NativeFormat);
直接访问Windows注册表
在Windows上,QSettings允许您访问在系统注册表中用QSettings编写的设置(或受支持格式的设置,例如字符串数据)。 这是通过构造QSettings对象和注册表中的路径以及QSettings :: NativeFormat来完成的。例如:
QSettings settings("HKEY_CURRENT_USER\\Software\\Microsoft\\Office",
QSettings::NativeFormat);
可以照常通过QSettings对象读取或写入出现在指定路径下的所有注册表项(使用正斜杠而不是反斜杠)。 例如:
settings.setValue("11.0/Outlook/Security/DontTrustInstalledFiles", 0);
请注意,如上所述,QSettings使用反斜杠字符来分隔子项。 结果,您不能读取或写入包含斜杠或反斜杠的Windows注册表项; 如果需要,您应该使用本机Windows API。
在Windows上访问通用注册表设置
在Windows上,键可能同时具有值和子键。 通过使用“默认”或“”可以访问其默认值。 代替子项:
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”和“.”将被视为常规子键。
平台限制
虽然QSettings尝试理顺不同支持平台之间的差异,但在移植应用程序时仍应注意一些差异:
- Windows系统注册表具有以下限制:子项不能超过255个字符,条目的值不能超过16,383个字符,并且键的所有值都不能超过65,535个字符。解决这些限制的一种方法是使用IniFormat而不是NativeFormat存储设置。
- 在Windows上,当使用Windows系统注册表时,QSettings不会保留该值的原始类型。因此,设置新值时,值的类型可能会更改。例如,类型为REG_EXPAND_SZ的值将更改为REG_SZ。
- 在macOS和iOS上,allKeys()将为适用于所有应用程序的全局设置返回一些额外的键。可以使用value()读取这些键,但不能更改它们,只能对其进行阴影处理。调用setFallbacksEnabled(false)将隐藏这些全局设置。
- 在macOS和iOS上,QSettings使用的CFPreferences API需要Internet域名而不是组织名称。为了提供统一的API,QSettings会从组织名称中得出伪造的域名(除非组织名称已经是域名,例如OpenOffice.org)。该算法在公司名称后附加“ .com”,并用连字符替换空格和其他非法字符。如果要指定其他域名,请在main()函数中调用QCoreApplication :: setOrganizationDomain(),QCoreApplication :: setOrganizationName()和QCoreApplication :: setApplicationName(),然后使用默认的QSettings构造函数。另一种解决方案是使用预处理器指令,例如:
#ifdef Q_OS_MAC
QSettings settings("grenoullelogique.fr", "Squash");
#else
QSettings settings("Grenoulle Logique", "Squash");
#endif
- 在macOS上,访问不属于当前用户(即SystemScope)的设置的权限已随10.7(Lion)更改。 在该版本之前,具有管理员权限的用户可以访问这些权限。 对于10.7和10.8(Mountain Lion),只有root可以。 但是,10.9(Mavericks)再次更改了该规则,但仅适用于本机格式(plist文件)。
另请参见QVariant,QSessionManager,设置编辑器示例和应用程序示例。
成员类型文档
枚举QSettings :: Format
此枚举类型指定QSettings使用的存储格式。
Constant | Value | Description |
---|---|---|
QSettings::NativeFormat |
0 |
使用最适合平台的存储格式存储设置。 在Windows上,这意味着系统注册表。 在macOS和iOS上,这意味着CFPreferences API; 在Unix上,这意味着INI格式的文本配置文件。 |
QSettings::Registry32Format |
2 |
仅限Windows:从在64位Windows上运行的64位应用程序显式访问32位系统注册表。 在32位Windows上或从64位Windows上的32位应用程序中,其作用与指定NativeFormat相同。 这个枚举值是在Qt 5.7中添加的。 |
QSettings::Registry64Format |
3 |
仅限Windows:从在64位Windows上运行的32位应用程序显式访问64位系统注册表。 在32位Windows上或在64位Windows上的64位应用程序中,此操作与指定NativeFormat相同。 这个枚举值是在Qt 5.7中添加的。 |
QSettings::IniFormat |
1 |
将设置存储在INI文件中。 请注意,从INI文件读取设置时不会保留类型信息。 所有值将作为QString返回。 |
QSettings::InvalidFormat |
16 |
registerFormat()返回的特殊值。 |
在Unix上,NativeFormat和IniFormat的含义相同,不同之处在于文件扩展名不同(.conf用于NativeFormat,.ini用于IniFormat)。
INI文件格式是Qt在所有平台上都支持的Windows文件格式。 在没有INI标准的情况下,我们尝试遵循Microsoft的操作,但以下情况除外:
-
如果您存储QVariant无法转换为QString的类型(例如QPoint,QRect和QSize),则Qt使用基于@的语法对类型进行编码。 例如:
pos = @Point(100 100)
为了最大程度地减少兼容性问题,任何未出现在值的第一个位置或其后没有Qt类型(点,矩形,大小等)的@均被视为普通字符。
-
尽管反斜杠是INI文件中的特殊字符,但是大多数Windows应用程序都不会在文件路径中转义反斜杠(\):
windir = C:\Windows
QSettings始终将反斜杠视为特殊字符,并且不提供用于读取或写入此类条目的API。
- INI文件格式对密钥的语法有严格的限制。 Qt通过使用%作为键中的转义字符来解决此问题。 另外,如果您保存一个顶级设置(其中没有斜杠的键,例如“ someKey”),它将显示在INI文件的“常规”部分中。 为避免覆盖其他键,如果使用诸如“ General / someKey”之类的键进行保存,则该键将位于“%General”部分,而不是“ General”部分。
- 遵循我们应该在接受的内容上保持自由,在生成的内容上保持保守的理念,QSettings将接受Latin-1编码的INI文件,但生成纯ASCII文件,其中非ASCII值使用标准INI转义序列进行编码。 为了使INI文件更具可读性(但兼容性可能较低),请调用setIniCodec()。
另请参见registerFormat()和setPath()。
typedef QSettings::ReadFunc
Typedef指向具有以下签名的函数的指针:
bool myReadFunc(QIODevice &device, QSettings::SettingsMap &map);
ReadFunc在registerFormat()中用作指向读取一组键/值对的函数的指针。 ReadFunc应该一次性读取所有选项,并返回SettingsMap容器中的所有设置,该容器最初为空。
另请参见WriteFunc和registerFormat()。
enum QSettings::Scope
该枚举指定设置是用户特定的还是由同一系统的所有用户共享的。
Constant | Value | Description |
---|---|---|
QSettings::UserScope |
0 |
Store settings in a location specific to the current user (e.g., in the user's home directory). |
QSettings::SystemScope |
1 |
Store settings in a global location, so that all users on the same machine access the same set of settings. |
另请参见setPath()。
typedef QSettings::SettingsMap
Typedef for QMap<QString, QVariant>.
另请参见registerFormat()。
enum QSettings::Status
可以使用以下状态值:
Constant | Value | Description |
---|---|---|
QSettings::NoError |
0 |
没有发生错误。 |
QSettings::AccessError |
1 |
发生访问错误(例如,尝试写入只读文件)。 |
QSettings::FormatError |
2 |
发生格式错误(例如,加载格式错误的INI文件)。 |
另请参见status()。
typedef QSettings::WriteFunc
Typedef指向具有以下签名的函数的指针:
bool myWriteFunc(QIODevice &device, const QSettings::SettingsMap &map);
WriteFunc在registerFormat()中用作指向写入一组键/值对的函数的指针。 WriteFunc仅被调用一次,因此您需要一次性输出设置。
另请参见ReadFunc和registerFormat()。
成员函数文档