当前位置: 首页 > news >正文

Qt中使用QSettings数据或结构体到INI文件

一、QSettings 概述

QSettings 是 Qt 框架提供的持久化配置管理类,用于存储和读取应用程序的配置数据(如用户偏好、窗口大小、最近打开文件等)。支持多种存储格式(如 INI 文件、注册表、JSON 等),跨平台使用,无需手动处理文件路径或格式差异。


二、核心功能

跨平台支持

  • Windows:默认使用注册表(HKEY_CURRENT_USER)。
  • macOS/iOS:使用属性列表(.plist 文件)。
  • Linux/Unix:默认使用 INI 文件(~/.config/组织名/应用名.conf)。

存储格式

  • QSettings::IniFormat:读写 INI 文件。
  • QSettings::NativeFormat:自动选择平台默认格式。
  • QSettings::registerFormat():自定义格式(如 JSON)。

数据层次结构

  • 支持分组(beginGroup()/endGroup())和键值对(setValue()/value())。

三、基本用法

初始化与存储

QSettings settings("MyCompany", "MyApp");  // 组织名和应用名  
settings.setValue("window/size", QSize(800, 600));  // 存储窗口大小  
settings.setValue("recentFiles", QStringList{"file1.txt", "file2.txt"});  // 存储列表  

读取与默认值

QSize size = settings.value("window/size", QSize(400, 300)).toSize();  // 读取并设默认值  
QStringList files = settings.value("recentFiles").toStringList();  // 读取列表  

分组管理

settings.beginGroup("network");  
settings.setValue("proxyEnabled", true);  
settings.endGroup();  // 结束分组  

四、高级特性

1、同步与原子性

  • sync():强制将内存数据写入磁盘(通常自动调用)。
  • atomicSync():确保写入操作的原子性(避免文件损坏)。

2、监听变化

  • 信号 QSettings::valueChanged(需手动检查变化)。

3、自定义存储路径

QSettings settings("/path/to/config.ini", QSettings::IniFormat);  // 指定文件路径  

4、结构体数据保存的问题

当尝试直接将结构体保存到INI文件时,会遇到以下问题:

  • 可读性差:保存后的数据会被转换为QByteArray形式的二进制数据,看起来像一堆乱码
  • 直接保存不可行:如果不做特殊处理,Qt不知道如何序列化和反序列化自定义结构体

解决方案:重载输入输出操作符
为了使结构体能够被QSettings正确保存和读取,需要在结构体中重载<<和>>操作符:

struct ClientConfig  {int tabIndex;    QString serverInfo;  // 重载数据流输出操作符friend QDataStream &operator << (QDataStream &out, const ClientConfig &clientConfig) {out << clientConfig.tabIndex;        out << clientConfig.serverInfo;        return out;}// 重载数据流输入操作符friend QDataStream &operator >> (QDataStream &in, ClientConfig &clientConfig) {in >> clientConfig.tabIndex;        in >> clientConfig.serverInfo;        return in;}
};

注册元数据类型
除了重载操作符外,还需要使用Q_DECLARE_METATYPE宏将结构体注册为元数据类型:

Q_DECLARE_METATYPE(ClientConfig)

写入配置

QSettings set("config.ini", QSettings::IniFormat);
ClientConfig clientConfig;// 填充结构体数据
clientConfig.tabIndex = 1;
clientConfig.serverInfo = "example.com";// 写入配置
set.beginGroup("ClientConfig");
set.setValue("clientConfig", QVariant::fromValue(clientConfig)); 
set.endGroup();

读取配置

QSettings set("config.ini", QSettings::IniFormat);
ClientConfig clientConfig;// 读取配置
set.beginGroup("ClientConfig");
clientConfig = set.value("clientConfig").value<ClientConfig>();
set.endGroup();

注意事项

  • 1、可读性问题: 虽然这种方法可以保存结构体,但INI文件中的内容会是二进制形式,不利于直接阅读和修改。如果可读性是首要考虑因素,建议:
    • 将结构体成员分别保存为独立的键值对
    • 或者将结构体转换为JSON等可读格式后再保存
  • 2、版本兼容性: 如果修改了结构体的成员变量,需要确保新旧版本的序列化/反序列化逻辑兼容
  • 3、性能考虑: 对于简单的配置项,直接使用基本类型可能更高效

五、注意事项

  1. 键名区分大小写"Window/Size""window/size" 视为不同键。
  2. 类型安全:读取时需明确转换类型(如 toInt()toString())。
  3. 性能:频繁读写时建议批量操作(beginGroup() 减少键名重复)。

六、源码分享

在这里插入图片描述

#include "mainwindow.h"
#include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);
}MainWindow::~MainWindow()
{delete ui;
}struct Config  {int tabIndex;QString serverInfo;// 重载数据流输出操作符friend QDataStream &operator << (QDataStream &out, const Config &clientConfig) {out << clientConfig.tabIndex;out << clientConfig.serverInfo;return out;}// 重载数据流输入操作符friend QDataStream &operator >> (QDataStream &in, Config &clientConfig) {in >> clientConfig.tabIndex;in >> clientConfig.serverInfo;return in;}
};Q_DECLARE_METATYPE(Config)void MainWindow::on_btnSave_clicked()
{QSettings set("config.ini", QSettings::IniFormat);Config clientConfig;// 填充结构体数据clientConfig.tabIndex = 1;clientConfig.serverInfo = "example.com";// 写入配置set.beginGroup("Config");set.setValue("Config", QVariant::fromValue(clientConfig));set.endGroup();
}void MainWindow::on_btnRead_clicked()
{QSettings set("config.ini", QSettings::IniFormat);Config clientConfig;// 读取配置set.beginGroup("Config");clientConfig = set.value("Config").value<Config>();qDebug()<<"serverInfo:"<<clientConfig.serverInfo;qDebug()<<"tabIndex:"<<clientConfig.tabIndex;set.endGroup();
}

在这里插入图片描述

http://www.xdnf.cn/news/1076419.html

相关文章:

  • 用 YOLOv8 + DeepSORT 实现目标检测、追踪与速度估算
  • 05【C++ 入门基础】内联、auto、指针空值
  • 物联网数据洪流下,TDengine 如何助 ThingLinks 实现 SaaS 平台毫秒级响应?
  • 在Linux中下载docker
  • 【SQL优化案例】索引创建不合理导致SQL消耗大量CPU资源
  • SpringBoot - 定时任务改Cron不重启,调度规则生效
  • RuoYi-Vue前后端分离版实现前后端合并
  • 用Fiddler中文版抓包工具掌控微服务架构中的接口调试:联合Postman与Charles的高效实践
  • docker desktop部署本地gitlab服务
  • 学习昇腾开发的第12天--安装第三方依赖
  • 基于springboot的养老院管理系统
  • LINUX2.6设备注册与GPIO相关的API
  • Vue3 中 Excel 导出的性能优化与实战指南
  • JavaScript 安装使用教程
  • ip网络基础
  • FastGPT与MCP:解锁AI新时代的技术密码
  • 百度轮岗:任命新CFO,崔珊珊退居业务二线
  • 使用Electron开发跨平台RSS阅读器:从零到一的完整指南
  • Linux查看空间大小相关命令内容
  • 数据结构复习4
  • 前端计算机视觉:使用 OpenCV.js 在浏览器中实现图像处理
  • Oracle 常用函数
  • 38.docker启动python解释器,pycharm通过SSH服务直连
  • 【软考高项论文】论信息系统项目的进度管理
  • Zookeeper安装使用教程
  • SQL规范
  • IDEA相关配置记录
  • 【中文核心期刊推荐】《计算机应用与软件》
  • Windows CMD命令分类大全
  • 前端开发面试题总结-原生小程序部分