Qt读取ini格式配置文件的类设计

目录

1.引言

2.QSettings

2.1.功能特点

2.2.基本用法

3.读取ini文件配置通用类设计

3.1.设计要点

3.2.完整实现

3.3.调用方法

4.总结


1.引言

        在编写应用程序的时,有些参数需要用户配置,那么这些参数就涉及到存储了,单从存储来讲,就有很多实现的方案,比如ini格式文件保存、xml格式文件保存、json格式文件保存,数据库保存等,其中ini格式文件保存比较简单,也是平时项目用的比较多的一种,下面就详细讲讲Qt中读取ini格式配置文件的方法和通用类设计。

2.QSettings

        QSettings 是 Qt 框架中用于读取和写入应用程序配置信息的类。它提供了一个跨平台的解决方案,可轻松地保存和获取应用程序的设置和状态。

2.1.功能特点

1)跨平台支持:QSettings能够自动适配不同的操作系统,确保配置数据能在不同平台间无缝迁移。无论是Windows的注册表、macOS的plist文件,还是INI文件或JSON格式的文件,QSettings都能轻松处理。

2)键值对存储:使用键值对的方式来存储和读取应用程序的设置信息,使得配置数据的管理变得简单直观。

3)多种存储格式:支持多种存储格式,包括NativeFormat(使用操作系统推荐的存储方式)、IniFormat(将数据保存为INI格式的文本文件)和CustomFormat(允许指定自定义的存储格式,但需配合自定义的QSettings backend实现)。

4)默认值支持:在读取设置值时,如果找不到指定的键,QSettings可以返回预设的默认值。

5)辅助方法:提供了一些辅助方法来处理组织和应用程序范围的设置,以及检查设置是否存在、删除设置项等功能。

2.2.基本用法

创建QSettings对象

在使用 QSettings 之前,首先需要创建一个 QSettings 对象。可以通过以下两种方式进行初始化:

使用应用程序的组织名称和应用程序名称进行初始化:

QSettings settings("组织名称", "应用程序名称");

使用配置文件路径进行初始化:

QSettings settings("ConfigFile/config.ini", QSettings::IniFormat);

注意:如果没有指定配置文件路径,QSettings 将使用平台特定的位置存储配置信息。

存储设置值

使用 setValue() 函数可以将键值对存储到配置文件中:

settings.setValue("key", "value");

读取设置值

使用 value() 函数可以读取配置文件中的键对应的值:

QVariant value = settings.value("键");  
// 如果需要特定类型的值,可以使用如下方式:  
QString stringValue = settings.value("键").toString();  
int intValue = settings.value("键").toInt();

如果要指定默认值,可以在读取时提供:

QString username = settings.value("username", "DefaultUser").toString();

设置系统编码

当ini文件的内容中可能有中文,如果不设置编码,就可能出现乱码。

QSettings iniRead(file, QSettings::IniFormat);
iniRead.setIniCodec("utf-8"); //解决中文乱码的情况

检查设置是否存在

bool exists = settings.contains("键");

删除设置项

使用 remove() 函数可以删除配置文件中的指定键:

settings.remove("key");

持久化设置

在多线程环境中,如果需要确保数据立即写入持久存储,可以使用sync()方法:

settings.setValue("Setting1", "Value1");  
settings.sync(); // 强制立即写入

访问子组

settings.beginGroup("Window");  
settings.setValue("Width", 800);  
settings.endGroup(); // 可选,用于提高代码可读性

综合示例:

以下是一个使用QSettings保存和恢复窗口位置、大小等设置的示例:

#include <QApplication>  
#include <QMainWindow>  
#include <QSettings>  
  
int main(int argc, char *argv[]) {  
    QApplication app(argc, argv);  
    QMainWindow window;  
    window.setWindowTitle("QSettings Example");  
  
    // Load settings  
    QSettings settings("YourCompany", "YourApp");  
    window.resize(settings.value("WindowSize", QSize(640, 480)).toSize());  
    window.move(settings.value("WindowPosition", QPoint(100, 100)).toPoint());  
  
    // Connect signals to save settings when necessary  
    QObject::connect(&window, &QMainWindow::windowStateChanged, [&settings](Qt::WindowState state) {  
        if (state == Qt::WindowMaximized)  
            settings.setValue("WindowState", "maximized");  
        else  
            settings.setValue("WindowState", "normal");  
    });  
    QObject::connect(&window, &QMainWindow::moveEvent, [&](QMoveEvent *event) {  
        settings.setValue("WindowPosition", event->pos());  
    });  
    QObject::connect(&window, &QMainWindow::resizeEvent, [&](QResizeEvent *event) {  
        settings.setValue("WindowSize", event->size());  
    });  
  
    window.show();  
    return app.exec();  
}

在这个示例中,我们创建了一个QSettings实例,并在窗口初始化时从其中加载先前保存的尺寸和位置。同时,连接了窗口状态变化、移动和调整大小的信号,以便在这些事件发生时自动更新存储的设置。

3.读取ini文件配置通用类设计

3.1.设计要点

1)应用程序用ini保存系统的配置,一般来说整个程序就一份,可以用单实例模式来实现整个类:

设计模式之单例模式-CSDN博客

class CShortWaveConfig
{
protected:
	CShortWaveConfig();
	~CShortWaveConfig();
	
    ...

public:
	static CShortWaveConfig& instance();

    ....
};

2)普通的编程思路是一行一行得读取ini文件,然后分别保存到变量中,这样做不具有批量操性;转变一下思路,可以一次性把整个文件读取出来,保存到QMap中,关键代码如下:

class CShortWaveConfig
{
protected:
    bool loadConfig();

    。。。
private:
	QMap<QString, QVariant> m_value;
};

bool CShortWaveConfig::loadConfig()
{
	。。。

	QStringList allKeys = iniRead.allKeys();
	for (auto& it : allKeys) {
		m_value[it] = iniRead.value(it);
	}
	return true;
}

3)元素的访问,每个元素的类型不知道,可利用C++中的模板把元素的类型T传入,判断是否可以从QVariant中的类型转换成T,关键代码如下:

template<typename T>
T value(const QString& key) {
    auto item = m_value.find(key);
    if (item != m_value.end()) {
		const QVariant& value1 = item.value();
		if (value1.canConvert<T>()) {
			return value1.value<T>();
		}
		assert(false);
	}
		
    。。。
}

4)元素的访问时,如果传入的路径找不到元素,可以返回默认参数,关键代码如下:

template<typename T>
T value(const QString& key, const T& defalutValue) {
	auto item = m_value.find(key);
	if (item != m_value.end()) {
		。。。
	}
	return defalutValue;
}

3.2.完整实现

ShortWaveConfig.h

#ifndef _SHORT_WAVE_CONFIG_H_
#define _SHORT_WAVE_CONFIG_H_
#include <QString>
#include <QMap>
#include <QVariant>
#include <assert.h>
using namespace std;

class CShortWaveConfig
{
protected:
	CShortWaveConfig();
	~CShortWaveConfig();
	bool loadConfig();

public:
	static CShortWaveConfig& instance();

	template<typename T>
	T value(const QString& key, const T& defalutValue) {
		auto item = m_value.find(key);
		if (item != m_value.end()) {
			const QVariant& value1 = item.value();
			if (value1.canConvert<T>()) {
				return value1.value<T>();
			}
			assert(false);
		}
		return defalutValue;
	}

private:
	QMap<QString, QVariant> m_value;
};

#endif

ShortWaveConfig.cpp

#include "ShortWaveConfig.h"
#include <QFile>
#include <QApplication>
#include <QSettings>

CShortWaveConfig::CShortWaveConfig()
{
	bool result = loadConfig();
	assert(result);
}

CShortWaveConfig::~CShortWaveConfig()
{

}

bool CShortWaveConfig::loadConfig()
{
	QString file = QCoreApplication::applicationDirPath() + "/systemConfig.ini";
	if (!QFile::exists(file)) {
		return false;
	}

	QSettings iniRead(file, QSettings::IniFormat);
	iniRead.setIniCodec("utf-8"); //解决中文乱码的情况
	QStringList allKeys = iniRead.allKeys();
	for (auto& it : allKeys) {
		m_value[it] = iniRead.value(it);
	}
	return true;
}

CShortWaveConfig& CShortWaveConfig::instance()
{
	static CShortWaveConfig config;
	return config;
}

3.3.调用方法

//姓名
QString name = CShortWaveConfig::instance().value<QString>("Attr/name", "xiaoming");

//年龄
int age = CShortWaveConfig::instance().value<int>("Attr/age", 20);

4.总结

        本文详细介绍了 Qt 中的 QSettings 类,包括初始化、读取、写入和删除配置信息的操作。还讲解了在整个系统中怎么去设计系统配置文件读取类CShortWaveConfig。通过合理使用类CShortWaveConfig,您可以轻松管理和存储应用程序的配置信息,提高应用程序的灵活性和可维护性。

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

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

相关文章

探索设计的未来:了解设计师对生成式人工智能(AIGC)工具的采用

在数字化浪潮的推动下&#xff0c;设计行业正经历着一场革命性的变革。随着生成式人工智能&#xff08;AIGC&#xff09;技术的发展&#xff0c;设计师们迎来了前所未有的机遇与挑战。这些工具不仅重塑了传统的设计流程&#xff0c;还为设计师们提供了更广阔的创意空间和更高效…

vue模板语法v-html

模板语法v-html vue使用一种基于HTML的模板语法&#xff0c;使我们能够声明式的将其组件实例的数据绑定到呈现的DOM上&#xff0c;所有的vue模板都是语法层面的HTML&#xff0c;可以被符合规范的浏览器和HTML解释器解析。 一.文本插值 最基本的数据绑定形式是文本插值&#…

理解神经网络的通道数

理解神经网络的通道数 1. 神经网络的通道数2. 输出的宽度和长度3. 理解神经网络的通道数3.1 都是错误的图片惹的祸3.1.1 没错但是看不懂的图3.1.2 开玩笑的错图3.1.3 给人误解的图 3.2 我或许理解对的通道数3.2.1 动图演示 1. 神经网络的通道数 半路出嫁到算法岗&#xff0c;额…

【算法训练记录——Day41】

Day41——动态规划Ⅲ 1.理论基础——代码随想录2.纯01背包_[kamacoder46](https://kamacoder.com/problempage.php?pid1046)3.leetcode_416分割等和子集 背包&#xff01;&#xff01; 1.理论基础——代码随想录 主要掌握01背包和完全背包 物品数量&#xff1a; 只有一个 ——…

顶级5款有用的免费IntelliJ插件,提升你作为Java开发者的旅程

在本文中&#xff0c;我们将深入探讨IntelliJ IDEA插件——那些可以提升你生产力的神奇附加组件&#xff0c;并微调你的代码以达到卓越。我们将探索5款免费插件&#xff0c;旨在将你的开发水平提升到一个新的高度。 1. Test Data 使用Test Data插件进行上下文操作 作为开发者&a…

昇思学习打卡-5-基于Mindspore实现BERT对话情绪识别

本章节学习一个基本实践–基于Mindspore实现BERT对话情绪识别 自然语言处理任务的应用很广泛&#xff0c;如预训练语言模型例如问答、自然语言推理、命名实体识别与文本分类、搜索引擎优化、机器翻译、语音识别与合成、情感分析、聊天机器人与虚拟助手、文本摘要与生成、信息抽…

基于用户的协同过滤算法

目录 原理&#xff1a; 计算相似度&#xff1a; 步骤&#xff1a; 计算方法&#xff1a;Jaccard相似系数、余弦相似度。 推荐 原理&#xff1a; 先“找到相似用户”&#xff0c;再“找到他们喜欢的物品”--->人以群分。即&#xff0c;给用户推荐“和他兴趣相似的其他用…

运维管理一体化:构建多维一体化的运维体系

本文来自腾讯蓝鲸智云社区用户&#xff1a;CanWay 摘要&#xff1a;笔者根据自身的技术和行业理解&#xff0c;解析运维一体化的内涵和实践。 涉及关键词&#xff1a;一体化运维、平台化运维、数智化运维、运维PaaS、运维工具系统、蓝鲸等。 本文作者&#xff1a;嘉为蓝鲸运维…

微信小程序 typescript 开发日历界面

1.界面代码 <view class"o-calendar"><view class"o-calendar-container" ><view class"o-calendar-titlebar"><view class"o-left_arrow" bind:tap"prevMonth">《</view>{{year}}年{{month…

react框架,使用vite和nextjs构建react项目

react框架 React 是一个用于构建用户界面(UI)的 JavaScript 库,它的本质作用是使用js动态的构建html页面&#xff0c;react的设计初衷就是为了更方便快捷的构建页面&#xff0c;官方并没有规定如何进行路由和数据获取&#xff0c;要构建一个完整的react项目&#xff0c;我们需要…

Frrouting快速入门——OSPF组网(一)

FRR简介 FRR是FRRouting的简称&#xff0c;是一个开源的路由交换软件套件。其作者源自老牌项目quaga的成员&#xff0c;也可以算是quaga的新版本。 使用时一般查看此文档&#xff1a;https://docs.frrouting.org/projects/dev-guide/en/latest/index.html FRR支持的协议众多…

Unity 实现UGUI 简单拖拽吸附

获取鼠标当前点击的UI if(RectTransformUtility.RectangleContainsScreenPoint(rectTransform, Input.mousePosition)) {return rectTransform.gameObject; } 拖拽 在Update 中根据鼠标位置实时更新拖拽的图片位置。 itemDrag.transform.position Input.mousePosition; …

Windows安全认证机制——Windows常见协议

一.LLMNR协议 1.LLMNR简介 链路本地多播名称解析&#xff08;LLMNR&#xff09;是一个基于域名系统&#xff08;DNS&#xff09;数据包格式的协议&#xff0c;使用此协议可以解析局域网中本地链路上的主机名称。它可以很好地支持IPv4和IPv6&#xff0c;是仅次于DNS解析的名称…

JavaFx基础知识

1.Stage 舞台 如此这样的一个框框&#xff0c;舞台只是这个框框&#xff0c;并不管里面的内容 public void start(Stage primaryStage) throws Exception {primaryStage.setScene(new Scene(new Group()));primaryStage.getIcons().add(new Image("/icon/img.png"))…

昇思25天学习打卡营第15天|ResNet50图像分类

学AI还能赢奖品&#xff1f;每天30分钟&#xff0c;25天打通AI任督二脉 (qq.com) ResNet50图像分类 图像分类是最基础的计算机视觉应用&#xff0c;属于有监督学习类别&#xff0c;如给定一张图像(猫、狗、飞机、汽车等等)&#xff0c;判断图像所属的类别。本章将介绍使用ResN…

更改Anki笔记所应用的模板及其所属的牌组

对于Anki中的笔记&#xff0c;录入时总会为它指定模板以及所属的牌组&#xff0c;但是&#xff0c;如果发生教材版本变更&#xff0c;我们可能会用新的模板添加笔记&#xff0c;也会使用新的牌组&#xff0c;但是原来所做的笔记中也有一些完全可以继续使用&#xff0c;如果可以…

超详细的 C++中的封装继承和多态的知识总结<1.封装与继承>

引言 小伙伴们都知道C面向对象难&#xff0c;可是大家都知道&#xff0c;这个才是C和C的真正区别的地方&#xff0c;也是C深受所有大厂喜爱的原因&#xff0c;它的原理更接近底层&#xff0c;它的逻辑更好&#xff0c;但是学习难度高&#xff0c;大家一定要坚持下来呀&#xff…

【实验室精选】PFA反应瓶带鼓泡球 高效气体鼓泡 化学分析优选

PFA反应瓶带鼓泡球是一种特殊设计的实验室容器&#xff0c;它集成了鼓泡球和PFA&#xff08;全氟烷氧基&#xff09;材料的反应瓶&#xff0c;用于气体的鼓泡和液体的混合。以下是它的一些特点和用途&#xff1a; 特点&#xff1a; 鼓泡球设计&#xff1a;鼓泡球周围布满小孔&…

Unity热更方案HybridCLR+YooAsset,纯c#开发热更,保姆级教程,从零开始

文章目录&#xff1a; 一、前言二、创建空工程三、接入HybridCLR四、接入YooAsset五、搭建本地资源服务器Nginx六、实战七、最后 一、前言 unity热更有很多方案&#xff0c;各种lua热更&#xff0c;ILRuntime等&#xff0c;这里介绍的是YooAssetHybridCLR的热更方案&#xff0…

60种AI工具用法 学会探索AI的无限可能

外面还在卖的课程&#xff0c;学会探索AI的无限可能&#xff0c;从构建精准的提示词到获取个性化新闻&#xff0c;从快速制作PPT到短视频内容的智能提炼&#xff0c;再到编程、股市分析和视频剪辑&#xff0c;AI工具助您工作学习效率飞跃提升&#xff01; 百度网盘 请输入提取…