【Qt之QSetting】介绍及使用

概述

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.mfbz.cn/a/108324.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

通过阿里云创建accessKeyId和accessKeySecret

我们想实现服务端向个人发送短信验证码 需要通过accessKeyId和accessKeySecret 这里可以白嫖阿里云的 这里 我们先访问阿里云官网 阿里云地址 进入后搜索并进入短信服务 如果没登录 就 登录一下先 然后在搜索框搜索短信服务 点击进入 因为我也是第一次操作 我们一起点免费开…

《算法通关村—计算器|逆波兰问题解析》

《算法通关村—计算器|逆波兰问题解析》 计算器问题 描述 LeetCode227.给你一个字符串表达式 s &#xff0c;请你实现一个基本计算器来计算并返回它的值。整数除法仅保留整数部分。 输入&#xff1a;s "32*2" 输出&#xff1a;7基本思路&#xff1a;理解题目&a…

响应式相册写真摄影网站模板源码

模板信息&#xff1a; 模板编号&#xff1a;28526 模板编码&#xff1a;UTF8 模板颜色&#xff1a;黑白 模板分类&#xff1a;摄像、婚庆、家政、保洁 适合行业&#xff1a;婚纱摄影类企业 模板介绍&#xff1a; 本模板自带eyoucms内核&#xff0c;无需再下载eyou系统&#x…

【SPSS】基于RFM+Kmeans聚类的客户分群分析(文末送书)

&#x1f935;‍♂️ 个人主页&#xff1a;艾派森的个人主页 ✍&#x1f3fb;作者简介&#xff1a;Python学习者 &#x1f40b; 希望大家多多支持&#xff0c;我们一起进步&#xff01;&#x1f604; 如果文章对你有帮助的话&#xff0c; 欢迎评论 &#x1f4ac;点赞&#x1f4…

精讲双向链表的销毁

相信大家各位学习双向链表的时候对链表的销毁&#xff0c;都或多或少有些小疑惑&#xff0c;我到底是传一级指针还是传二级指针 木关系&#xff0c;这些都是小意思&#xff0c;今天我将为大家share 一下关于到底如何进行正确传指针 对于链表是销毁其实就是对链表进行一个结点一…

Qt配置OpenCV教程,亲测已试过

详细版可参考&#xff1a;Qt配置OpenCV教程&#xff0c;亲测已试过&#xff08;详细版&#xff09;_qt opencv_-_Matrix_-的博客-CSDN博客 软件准备&#xff1a;QtOpenCVCMake (QtOpenCV安装不说了&#xff0c;CMake的安装&#xff0c;我用的是&#xff1a;可参考博客&#x…

Java集成腾讯云OCR身份证识别接口

一、背景 项目用到身份证识别获取人员信息的功能&#xff0c;于是想到了腾讯云提供这样的API。在整合代码过程都很顺利&#xff0c;利用腾讯云官方SDK很快集成进来。但是在上测试环境部署时有了新的问题&#xff0c;通过Nginx代理后的环境无法访问到目标腾讯云接口&#xff0c;…

云起无垠典型案例入选《2023软件供应链安全洞察》报告

近日&#xff0c;历时6个月&#xff0c;由ISC编制的《2023软件供应链安全洞察》报告&#xff08;以下简称《报告》&#xff09;正式对外发布。《报告》围绕软件供应链安全现状、技术内核、治理指南、落地实践展开&#xff0c;以期为行业从业者提供有价值的信息和洞见&#xff0…

飞利浦双串口51单片机485网关

主要功能将PC端的数据接收下来&#xff0c;分发到不同的设备&#xff0c;也是轮询设备数据读取回来&#xff0c;打包回传到PC端&#xff0c;数据包包头包尾识别&#xff0c;数据校验&#xff0c;接收超时处理&#xff0c;将协议结构化处理&#xff0c;协议的改动不需要改动程序…

Python学习笔记--初始化函数

六、初始化函数 1、什么是初始化函数 初始化函数的意思是&#xff0c;当你创建一个实例的时候&#xff0c;这个函数就会被调用。 比如&#xff1a; 当代码在执行 a ClassA() 的语句时&#xff0c;就自动调用了 __init__(self) 函数。 而这个 __init__(self) 函数就是初始化…

为什么数组的下标是从0开始呢?

我们在许多的编程语言中&#xff0c;大部分的数组下标都是从零开始的&#xff0c;那为什么不是从一开始的呢&#xff1f; 首先我们&#xff0c;先要了解数组相关的定义。 数组&#xff08;Array&#xff09;是一种线性表数据结构。它用一组连续的内存空间&#xff0c;来存储一…

【Linux】虚拟机安装Linux、客户端工具及Linux常用命令(详细教程)

目录 一、导言 1、引言 2、使用场景 二、Linux安装 1、安装 2、网络配置 2.1、查看网络配置 2.2、更改网络配置 三、安装客户端工具 1、介绍 2、安装MobaXterm 3、换源 4、拍照功能 四、常用命令 一、导言 1、引言 Linux是一个开源的操作系统内核&#xff0c;它最…

粤嵌实训医疗项目--day03(Vue + SpringBoot)

往期回顾 粤嵌实训医疗项目day02&#xff08;Vue SpringBoot&#xff09;-CSDN博客 粤嵌实训医疗项目--day01&#xff08;VueSpringBoot&#xff09;-CSDN博客 目录 一、SpringBoot AOP的使用 二、用户模块-注册功能&#xff08;文件上传&#xff09; 三、用户模块-注册实现…

【SpringBoot】Docker部署

docker部署是主流的部署方式&#xff0c;极大的方便了开发部署环境&#xff0c;保持了环境的统一&#xff0c;也是实现自动化部署的前提。 1 项目的目录结构 package: 点击打包&#xff0c;生成 xxx-SNAPSHOT.jar target目录: 打包生成目录&#xff0c;生成的jar存放位置Docke…

D-Nerf:用于动态场景表示的神经辐射场

Pumarola A, Corona E, Pons-Moll G, et al. D-nerf: Neural radiance fields for dynamic scenes[C]//Proceedings of the IEEE/CVF Conference on Computer Vision and Pattern Recognition. 2021: 10318-10327. D-Nerf 较 NeRF 的改进 1 就是能够建模移动或变形的物体&#…

分享个包含各省、市、区的编码数据的在线静态资源脚本

在翻《SpringBootVue3》——十三尼克陈作者的大型前后端分离项目实战里面&#xff0c;在看到地址管理的部分时&#xff0c;发现了该作者记录有一个静态的地址资源脚本 这里做个记录&#xff0c;打点 一、引入js <script src"https://s.yezgea02.com/1641120061385/td…

python opencv之图像分割、计算面积

以下代码是一个基于K-means聚类算法进行图像分割的实现。通过读取一个彩色图像&#xff0c;将其转化为二维数组形式。然后使用K-means算法对像素点进行聚类&#xff0c;聚类个数为7。根据聚类后的标签值对像素点进行着色&#xff0c;并创建掩膜图像。接着使用形态学开运算和闭运…

C语言编写图形化界面-创建按钮-为其指定样式

文章目录 前置章节指定窗口样式给按钮加边框扁平化按钮复选框样式按钮自动复选框 单选按钮三态按钮自动三态按钮 默认按钮样式&#xff08;对话框Enter键&#xff09; 设置按钮位置和大小封装函数 前置章节 开始之前&#xff0c;需要学习以下章节&#xff1a; 创建窗口 窗口过…

Jupyter Notebook还有魔术命令?太好使了

在Jupyter Notebooks中&#xff0c;Magic commands&#xff08;以下简称魔术命令&#xff09;是一组便捷的功能&#xff0c;旨在解决数据分析中的一些常见问题&#xff0c;可以使用%lsmagic 命令查看所有可用的魔术命令 插播&#xff0c;更多文字总结指南实用工具科技前沿动态…

【鸿蒙软件开发】Stage模型开发概述应用/组件级配置

文章目录 前言一、基本概念1.1 UIAbility 组件1.2 ExtensionAbility 组件1.3 Context1.4 AbilityStage1.5 Stage模型开发流程应用组件开发了解进程模型了解线程模型应用配置文件 二、Stage模型应用/组件级配置2.1 为什么需要这个操作2.2 应用包名配置2.3 应用图标和标签配置2.4…
最新文章