【Qt之QSetting】介绍及使用

news2024/11/15 13:41:10

概述

QSettings类提供了一种持久的、与平台无关的应用程序设置存储功能。
用户通常期望一个应用能在不同会话中记住其设置(窗口大小和位置,选项等)。在Windows上,这些信息通常存储在系统注册表中;在macOSiOS上,存储在属性列表文件中;在Unix系统上,由于缺乏标准,许多应用程序(包括KDE应用程序)使用INI文本文件。
QSettings是对这些技术的抽象,在可移植性的基础上,使您能够保存和恢复应用程序设置。它还支持自定义的存储格式。
QSettings的API基于QVariant,允许您以最小的努力保存大多数基于值的类型,如QString、QRect和QImage等。
如果您只需要一个非持久的基于内存的结构,请考虑使用QMap<QString, QVariant>替代。

基本用法

创建QSettings对象时,必须传递您的公司组织的名称以及应用程序的名称。例如,如果您的产品名称为Star Runner,公司名为MySoft,您应该如下构造QSettings对象:

QSettings settings("MySoft", "Star Runner");

可以在堆上(使用new)或栈上创建QSettings对象。构造和销毁QSettings对象非常快速。
如果在应用程序的多个地方使用QSettings,可以使用QCoreApplication::setOrganizationName()QCoreApplication::setApplicationName()来指定组织名称和应用程序名称,然后使用默认的QSettings构造函数:

QCoreApplication::setOrganizationName("MySoft");
QCoreApplication::setOrganizationDomain("mysoft.com");
QCoreApplication::setApplicationName("Star Runner");
...
QSettings settings;

(这里还指定了组织的互联网域。在设置了互联网域的情况下,macOS和iOS会使用互联网域来标识应用程序,而不是组织名称,因为macOS和iOS应用程序通常使用互联网域来标识自己。如果未设置域,将从组织名称派生一个虚假的域。有关详细信息,请参阅下面的特定平台的注释。)
QSettings存储设置。每个设置由一个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类型

由于QVariantQt Core模块的一部分,因此不能提供转换函数到Qt GUI的数据类型,如QColor、QImage和QPixmap。换句话说,QVariant中没有toColor()、toImage()或toPixmap()等函数。
相反,您可以使用QVariant::value()qVariantValue()模板函数。例如:

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

反向转换(例如,从QColor到QVariant)对于QVariant支持的所有数据类型,包括与GUI相关的类型都是自动的:

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

使用qRegisterMetaType()qRegisterMetaTypeStreamOperators()注册的自定义类型也可以使用QSettings进行存储。

部分和键的语法

设置键可以包含任何Unicode字符。Windows注册表和INI文件使用不区分大小写的键,而macOSiOS上的CFPreferences API使用区分大小写的键。为了避免可移植性问题,请遵循以下简单规则:

  1. 始终使用相同的大小写引用相同的键。例如,如果在代码的某个地方将键称为"text fonts",请不要在其他地方将其称为"Text Fonts"
  2. 避免只有大小写不同的键名称。例如,如果有一个名为"MainWindow"的键,请不要使用"mainwindow"保存另一个键。
  3. 不要在部分或键名中使用斜线(‘/‘和’’)。反斜杠字符用于分隔子键(见下文)。在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。在查找值时,按照以下顺序搜索最多四个位置:

  1. Star Runner应用程序的特定用户位置
  2. 所有MySoft应用程序的特定用户位置
  3. Star Runner应用程序的系统范围位置
  4. 所有MySoft应用程序的系统范围位置
    (有关Qt支持的不同平台上这些位置的信息,请参阅下面的特定平台的注释。)
    如果在第一个位置找不到键,则继续在第二个位置搜索,依此类推。这使您能够存储系统范围或组织范围的设置,并可以在每个用户或每个应用程序的基础上进行覆盖。要关闭此机制,请调用setFallbacksEnabled(false)。
    虽然可以从四个位置读取所有键,但只有第一个文件(与当前正在处理的应用程序相关的特定用户位置)可以写入。要写入其他文件,请省略应用程序名称和/或指定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"表示在读取时该位置用作后备。
在这里插入图片描述
这种机制的美妙之处在于它适用于Qt支持的所有平台,并且仍然提供了很大的灵活性,而无需指定任何文件名或注册表路径。
如果您想在所有平台上都使用INI文件而不是本地API,可以将QSettings::IniFormat作为QSettings构造函数的第一个参数,后跟作用域、组织名称和应用程序名称:

QSettings settings(QSettings::IniFormat, QSettings::UserScope,
                   "MySoft", "Star Runner");

Settings Editor示例允许您尝试不同设置位置以及打开或关闭后备机制。

恢复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("", QPoint(200, 200)).toPoint());
    settings.endGroup();
}

有关为什么调用QWidget::resize()QWidget::move()而不是QWidget::setGeometry()以恢复窗口的几何形状的讨论,请参阅窗口几何形状。
readSettings()writeSettings()函数必须从主窗口的构造函数和close事件处理程序中调用,如下所示:

MainWindow::MainWindow()
{
    ...
    readSettings();
}

void MainWindow::closeEvent(QCloseEvent *event)
{
    if (userReallyWantsToQuit()) {
        writeSettings();
        event->accept();
    } else {
        event->ignore();
    }
}

有关使用QSettings的自包含示例,请参见Application示例。

同时从多个线程或进程访问设置

QSettings是可重入的。这意味着可以同时在不同的线程中使用不同的QSettings对象。即使这些QSettings对象引用相同的磁盘文件(或系统注册表中的相同条目),此保证仍然有效。如果通过一个QSettings对象修改了一个设置,这个更改将立即对在同一位置操作并且在同一进程中存在的任何其他QSettings对象可见。
可以安全地从不同的进程(可以是同时运行的应用程序的不同实例或完全不同的应用程序)读取和写入相同的系统位置。它使用建议性文件锁定和智能合并算法来确保数据的完整性。请注意,sync()方法会导入其他进程所做的更改(除了写入这个QSettings的更改)。

常用方法

以下是QSettings类的一些常用方法的介绍。

构造函数:

  • QSettings(const QString& organization, const QString& application = QString(), QObject *parent = nullptr)
  • 使用组织名称和应用程序名称创建一个QSettings对象。默认情况下,QSettings使用基于平台的本地存储机制。
    • organization:组织名称
    • application:应用程序名称(可选)
    • parent:父级QObject对象(可选)

读取和写入值:

  • value(const QString& key, const QVariant& defaultValue = QVariant()):读取指定键的值,如果键不存在则返回defaultValue。返回QVariant类型的值。
  • setValue(const QString& key, const QVariant& value):设置指定键的值。
  • remove(const QString& key):删除指定键及其对应的值。
  • clear():清除所有的设置键和值。

设置默认值:

  • setDefaultFormat(QSettings::Format format):为所有新创建的QSettings对象设置默认格式(例如,INI格式或注册表格式)。
  • setDefaultScope(QSettings::Scope scope):为所有新创建的QSettings对象设置默认作用域(用户范围或系统范围)。

读取和写入组:

  • beginGroup(const QString& prefix):开始一个以prefix为前缀的设置组。
  • endGroup():结束当前的设置组。

同步操作:

  • sync():将所有的更改写入到永久存储,确保数据的同步。通常,QSettings会自动定期执行这个操作,但在某些情况下可能需要手动调用。

获取设置信息:

  • fileName():返回与当前QSettings对象关联的文件名。
  • scope():返回当前QSettings对象的作用域(用户范围或系统范围)。
  • organizationName():返回当前QSettings对象的组织名称。
  • applicationName():返回当前QSettings对象的应用程序名称。

注意:QSettings还提供了其他一些方法,例如支持跨线程和进程读写设置,以及对设置键和值进行迭代和查询。

示例

以下是一个使用QSettings的示,包含了常用的成员方法:

#include <QCoreApplication>
#include <QSettings>
#include <QDebug>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    // 创建 QSettings 对象
    QSettings settings("MyCompany", "MyApp");

    // 设置值
    settings.setValue("username", "John");
    settings.setValue("password", "123456");

    // 获取值
    QString username = settings.value("username").toString();
    QString password = settings.value("password").toString();

    qDebug() << "Username:" << username;
    qDebug() << "Password:" << password;

    // 检查是否存在某个键
    if (settings.contains("username")) {
        qDebug() << "The 'username' key exists";
    }

    // 移除一个键
    settings.remove("password");

    // 通过分组设置值,创建一个新的分组
    settings.beginGroup("Server");
    settings.setValue("host", "localhost");
    settings.setValue("port", 8080);
    settings.endGroup();

    // 在分组中获取值
    QString serverHost = settings.value("Server/host").toString();
    int serverPort = settings.value("Server/port").toInt();

    qDebug() << "Server Host:" << serverHost;
    qDebug() << "Server Port:" << serverPort;

    // 将更改刷新到磁盘上的配置文件中
    settings.sync();

    return a.exec();
}

结果

在这里插入图片描述

示例步骤:

  1. 创建了一个名为"MyApp"的应用程序设置,并设置了一些值。
  2. 通过value()方法获取这些值并输出。使用contains()方法检查特定的键是否存在,并使用remove()方法移除了"password"键。
  3. 使用beginGroup()和endGroup()方法创建了一个名为"Server"的分组,并在该分组中设置了一些值。
  4. 通过sync()方法将更改刷新到配置文件中。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1133562.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MySQL数据库 #4

文章目录 一、MySQL外键基本概念1. 表与表之间的关系1.一对多的表关系2.多对多3.一对一注意事项 2.多表查询1.子查询2.数据准备3.连表查询&#xff08;重点&#xff09; 二、多表查询练习题1.习题试题的SQL文件2.Navicata可视化软件1.连接数据库2 操作数据库3.导入备份4.查询数…

01. 板载硬件资源和开发环境

一、板载硬件资源 STM32F4VGT6-DISCOVERY硬件资源如下&#xff1a; (1). STM32F407VGT6微控制器有1M的FLASH存储器&#xff0c;192K的RAM&#xff0c;LQFP100封装 (2). 板上的ST-LINK_V2可以使用选择的方式把套件切换成一个独立的ST-LINK/V2来 使用&#xff08;可以使用SWD…

UML中类之间的六种主要关系

UML中类之间的六种主要关系: 继承&#xff08;泛化&#xff09;&#xff08;Inheritance、Generalization&#xff09;, 实现&#xff08;Realization&#xff09;&#xff0c;关联&#xff08;Association)&#xff0c;聚合&#xff08;Aggregation&#xff09;&#xff0c;组…

Java架构师内功嵌入式技术

目录 1 导学2 嵌入式微处理体系结构3 微处理器分类4 多核处理器5 嵌入式软件6 嵌入式系统6.1 系统组成7 嵌入式实时操作系统8 嵌入式软件设计9 软件开发工具想学习架构师构建流程请跳转:Java架构师系统架构设计 1 导学 嵌入式技术对软件架构的作用主要体现在以下几个方面: …

搜索二叉树实现(非递归版本)

目录 一&#xff0c;搜索二叉树是个啥&#xff1f; 二&#xff0c;搜索二叉树的实现 1.前期工作 2.方法实现 1.插入 2&#xff0c;查找 3.删除 三&#xff0c;实现二叉搜索树的全部代码 一&#xff0c;搜索二叉树是个啥&#xff1f; 话不多所&#xff0c;先给各位来一个…

查看linux下dns信息并修改

cat /etc/resolv.conf 查看dns 常用dns nameserver 114.114.114.114 nameserver 100.125.0.250 nameserver 8.8.8.8 nameserver 8.8.4.4 nameserver 192.168.122.1 nameserver 100.125.1.250 nameserver 100.125.1.251 nameserver 223.5.5.5 可以用vi 修改&#xff0c;修改后 …

【云原生】portainer管理多个独立docker服务器

目录 一、portainer简介 二、安装Portainer 1.1 内网环境下&#xff1a; 1.1.1 方式1&#xff1a;命令行运行 1.1.2 方式2&#xff1a;通过compose-file来启动 2.1 配置本地主机&#xff08;node-1&#xff09; 3.1 配置其他主机&#xff08;被node-1管理的节点服务器&…

spring常见问题汇总

1. 什么是spring? Spring是一个轻量级Java开发框架&#xff0c;最早有Rod Johnson创建&#xff0c;目的是为了解决企业级应用开发的业务 逻辑层和其他各层的耦合问题。它是一个分层的JavaSE/JavaEE full-stack&#xff08;一站式&#xff09;轻量级开源框架&#xff0c; 为开…

【LeetCode刷题日志】189.轮转数组

目录 1.题目描述 2.解题思路代码实现 方法一&#xff1a;使用额外的数组 解题思路&#xff1a; 代码实现&#xff1a; 方法二&#xff1a;环状替换 解题思路&#xff1a; 代码实现&#xff1a; 方法三&#xff1a;数组翻转 解题思路&#xff1a; 代码实现&#xff1a…

跨平台开发技术

目录 1.Qt1.简介2.优势3.劣势 2.NET CoreVue1.简介2.优点 3.Flutter1.简介2.优点3.缺点 4.Maui1.简介2.优点3.缺点 5.Avalonia1.简介2.优点3.缺点 6. Cordova1.简介2.优点3.缺点 7.Electron1.简介2.优点3.缺点 个人搜集资料并总结了一些跨平台开发技术&#xff0c;如有不足欢迎…

实战!RPA厂商选型分享

企业发展&#xff0c;必先科技先行&#xff0c;通过科技来提升内部运营、业务效率&#xff0c;从而达到降本、提质、增效的目标。但无论在技术选型亦或者厂商选择&#xff0c;都需要漫长的对比和调研&#xff0c;方能选择适合自身企业发展解决问题的技术和长期合作的技术伙伴。…

MathType7 公式编辑器嵌入Word\WPS,MathType 公式编辑常用小技巧

目录 1 MathType-7 下载 2 安装 4 嵌入word 5 嵌入wps 6 Mathtype 常用小技巧 6.1 四种插入公式的区别 &#xff1a; 6.2 MathType 常用快捷键 6.3 MathType转换公式 6.4 MathType公式编号 6.5 改变公式编号 6.6 mathtype 公式格式转换为latex格式 背景&#xff1a; w…

如何保卫您的网站:解决DDoS攻击与CC攻击

在当今数字化时代&#xff0c;网站安全是至关重要的。网络攻击如DDoS&#xff08;分布式拒绝服务&#xff09;和CC&#xff08;恶意请求洪水&#xff09;攻击可能会导致网站不稳定甚至不可用。本文将详细分析DDoS攻击和CC攻击的差异&#xff0c;以及如何使用CDN&#xff08;内容…

【C++】priority_queue仿函数

今天我们来学习C中另一个容器适配器&#xff1a;优先级队列——priority_queue&#xff1b;和C一个重要组件仿函数&#xff1a; 目录 一、priority_queue 1.1 priority_queue是什么 1.2 priority_queue的接口 1.2.1 priority_queue使用举例 二、仿函数 三、关于priority…

Linux C语言开发-D7D8运算符

算术运算符&#xff1a;-*/%&#xff0c;浮点数可以参与除法运算&#xff0c;但不能参与取余运算 a%b&#xff1a;表示取模或取余 关系运算符&#xff1a;<,>,>,<,,! 逻辑运算符:!,&&,|| &&,||逻辑运算符是从左到右&#xff0c;依次运算&#…

freeRTOS内部机制——栈的作用

上图中*pa 和*pb分别为R0&#xff0c;R1&#xff0c;调用C函数时&#xff0c;第一个参数保存在R0中第二个参数保存在R1中。这是约定。 指令保存在哪里&#xff1f; 指令保存在flash上面 LR等于什么? LR是返回地址&#xff0c;函数执行完了过后LR等于下一条指令的地址 运行…

JDK8新特性:Stream流

目录 1.获取Stream流 2.Stream流常见的中间方法 3.Stream流常见的终结方法 1、 Stream 是什么&#xff1f;有什么作用&#xff1f;结合了什么技术&#xff1f; ●也叫 Stream 流&#xff0c;是Jdk8开始新增的一套 API ( java . util . stream .*)&#xff0c;可以用于操作集…

【JAVA学习笔记】38 - 单例设计模式-静态方法和属性的经典使用

项目代码 https://github.com/yinhai1114/Java_Learning_Code/tree/main/IDEA_Chapter10/src/com/yinhai/final_ 一、什么是设计模式 1.静态方法和属性的经典使用 2.设计模式是在大量的实践中总结和理论化之后优选的代码结构、编程风格以及解决问题的思考方式。设计模式就像是…

【完美世界】被骂国漫之耻,石昊人设战力全崩,现在真成恋爱世界了

【侵权联系删除】【文/郑尔巴金】 深度爆料&#xff0c;《完美世界》动漫第135集预告片已经更新了&#xff0c;但是网友们对此却是一脸槽点。从预告中可以看出&#xff0c;石昊在和战王战天歌的大战中被打成重伤&#xff0c;最后云曦也被战天歌抓住。在云曦面临生死危机的时候…

AIGC底层数据探索——高质量数据助力大模型迭代升级

// 编者按&#xff1a;近年来&#xff0c;大模型的概念逐渐受到更广泛的关注&#xff0c;而谈及大模型就离不开对底层数据的探索。 大模型训练数据痛点与中文数据集现状&#xff1b;高质量数据定义&#xff1b;对话式数据模型实验&#xff1b;晴数智慧高质量数据解决方案。 文…