(12)功能实现:Qt实战项目之读写配置文件

回顾上一节课的内容,我们成功解锁了.db项目文件的创建技能。这节课,就让我们趁热打铁,一起来学习如何打开已创建的.db 项目文件 ,通过实现打开文件关于两个功能进一步探索读写配置文件的实现。

课程目标

本节课我们来学习读写配置文件,具体如下:

1、学习读写系统注册表、INI配置文件;

2、实现菜单栏的"文件-打开项目"按钮,读取系统注册表,默认显示出上一次打开的项目;

3、实现菜单栏的"帮助-关于"按钮,读INI配置文件获取信息;

定义打开文件的槽函数

首先在SubCfgTool类中定义打开项目的槽函数,定义为openProject()。然后绑定按钮点击信号与打开项目的槽函数,此过程可以参考之前的学习内容。

cpp 复制代码
connect(openProjAct, &QAction::triggered, this, &SubCfgTool::openProject);

接下来我们来实现打开项目的主要逻辑,前面的课程中我们在创建项目的时候,用到了QFileDialog::getExistingDirectory()函数来获取项目的存放路径,这节课我们来使用QFileDialog的另外一个静态函数getOpenFileName()来返回用户选择的文件。

cpp 复制代码
// 参数说明:
QString QFileDialog::getOpenFileName(
    QWidget *parent = nullptr,                // 父窗口
    const QString &caption = QString(),       // 对话框标题
    const QString &dir = QString(),           // 默认打开的目录
    const QString &filter = QString(),        // 文件类型过滤规则(如"数据库文件 (*.db);;文本文件 (*.txt)")
    QString *selectedFilter = nullptr,        // 输出参数:用户选中的过滤规则(可选)
    QFileDialog::Options options = Options()  // 对话框选项(如是否显示详细信息、是否只读等,可选)
);

选择.db文件后,再调用initDatabase()函数完成初始化。

cpp 复制代码
void SubCfgTool::openProject()
{
	QString strFileName;
	strFileName = QFileDialog::getOpenFileName(this, QStringLiteral("打开项目"), "", QStringLiteral("项目文件(*.db)"));
	if (strFileName.isEmpty())
	{
		return;
	}
	else
	{
		DBManager::getInstance()->initDatabase(strFileName);
	}
}

定义关于的槽函数

在SubCfgTool类中定义槽函数aboutDialog(),再绑定信号与槽函数。

cpp 复制代码
connect(aboutAct, &QAction::triggered, this, &SubCfgTool::aboutDialog);

槽函数的实现,将在接下来的内容中讲解。

cpp 复制代码
void SubCfgTool::aboutDialog()
{
    
}

QSetting类

我们用到一下新的类,QSettings 是 Qt 框架中用于轻松读写应用程序设置和配置的类。它提供了一种跨平台的方式来管理用户偏好、应用状态和持久化数据。在 Windows 系统中,它主要对接系统注册表(默认)或自定义 INI 文件,无需手动调用 Windows API 即可便捷操作系统级 / 应用级配置,是 Qt 开发中管理 Windows 配置的首选工具。

QSettings 操作系统注册表

结合上面打开项目的函数,如果我们打开项目时,需要记住上一次打开的目录,应该怎么做。特别是一些经常性的打开操作,我们希望其能记住上一次的打开目录,即便是在程序重启以后,也依然能记住。这里我们引入一个新的QSetting类。

像是记录上一次的打开目录这类配置信息,系统自动记录和读取即可,无需开放给用户编辑,所以这些配置信息我们统一放在注册表中存放,这些配置信息都是以键值的形式存储的,我们在DBManager类中封装两个函数,分别读取和写入

cpp 复制代码
bool setRegedit(QString strKey, QString strValue);    // 写入键值
QString getRegedit(QString strKey);                   // 根据键获取配置信息

函数实现如下:

  • QSettings对象我们指定写入的位置"HKEY_CURRENT_USER\Software\SubCfgTool\LastRecord"。
  • 参数QSettings::NativeFormat 是 Qt 框架中用于指定配置文件存储格式的枚举值,它表示使用操作系统原生的配置存储方式。
cpp 复制代码
bool DBManager::setRegedit(QString strKey, QString strValue)
{
	QSettings settings("HKEY_CURRENT_USER\\Software\\SubCfgTool\\LastRecord", QSettings::NativeFormat);
	settings.setValue(strKey, strValue);
	return true;
}
QString DBManager::getRegedit(QString strKey)
{
	QSettings settings("HKEY_CURRENT_USER\\Software\\SubCfgTool\\LastRecord", QSettings::NativeFormat);
	QString valueStr = settings.value(strKey).toString();
	return valueStr;
}

回到打开项目的函数,我们在每次打开文件之后,将路径信息写入到注册表

cpp 复制代码
void SubCfgTool::openProject()
{
        // *****
     
        // ***** 以上为其他内容

        
        // 获取路径
        QFileInfo fileInfo(strFileName);
        QString dirPath = fileInfo.absolutePath();  // 例如:"D:/Documents/Images"
        // 写入注册表
        DBManager::getInstance()->setRegedit("LastDBFilePath", dirPath);
}

同时,每次打开项目时,也要先查找一下注册表,看注册表中是否有记录上一次的打卡目录,并设置在QFileDialog::getOpenFileName的参数中,如下

cpp 复制代码
void SubCfgTool::openProject()
{
	// 获取上一次打开的目录
	QString strLastDBFilePath = DBManager::getInstance()->getRegedit("LastDBFilePath");

	QString strFileName;
	strFileName = QFileDialog::getOpenFileName(this, QStringLiteral("打开项目"), strLastDBFilePath, QStringLiteral("项目文件(*.db)"));
	if (strFileName.isEmpty())
	{
		return;
	}
	else
	{
		DBManager::getInstance()->initDatabase(strFileName);
	}

	// 获取路径
	QFileInfo fileInfo(strFileName);
	QString dirPath = fileInfo.absolutePath();  // 例如:"D:/Documents/Images"
	// 写入注册表
	DBManager::getInstance()->setRegedit("LastDBFilePath", dirPath);
}

编译运行测试效果,发现每次打开项目时,会自动定位到上一次打开的目录。

QSettings 操作 INI配置文件

若不想操作注册表,也可以读写INI配置文件,INI 是轻量级文本配置文件,适合需用户手动修改、可便携迁移、轻量简单的配置。

INI配置文件由节、键、值组成。同类的配置信息按照节组合在一起。

我们定义一个程序的配置文件cfg.ini,放在应用程序的目录下。 Release和Debug目录都放置。我们在cfg配置文件中定义公司名称、软件名称、软件版本等基本信息。

cpp 复制代码
[Base]
company = xiyou
toolname = SubCfgTool
version = 1.0.0

因为这个配置文件,主要以读取为主,所以我们只定义一个读取的函数。

  • QCoreApplication::applicationDirPath()用于获取当前程序的目录;
  • QSettings::IniFormat 表示使用 INI 格式 存储配置数据。
cpp 复制代码
QString DBManager::getIniCfg(QString strKey)
{
	// 构建完整的INI文件路径
	QString configPath = QCoreApplication::applicationDirPath() + "/cfg.ini";

	// 检查文件是否存在
	if (!QFileInfo::exists(configPath))
	{
		qWarning() << "INI文件不存在:" << configPath;
		return QString();
	}

	// 使用 INI 文件格式
	QSettings settings(configPath, QSettings::IniFormat);
	QString valueStr = settings.value(strKey).toString();

	return valueStr;
}

接下来我们来实现一下关于的函数aboutDialog(),该函数读出cfg.ini配置文件中的信息并展示。

cpp 复制代码
QDialog aboutWin(this);
    aboutWin.setWindowTitle(QStringLiteral("关于..."));
    aboutWin.setFixedSize(320, 150);

    QString strCompany = QStringLiteral("公司:") + DBManager::getInstance()->getIniCfg("Base/company");
    QString strToolName = QStringLiteral("工具:") + DBManager::getInstance()->getIniCfg("Base/toolname");
    QString strVersion = QStringLiteral("版本:") + DBManager::getInstance()->getIniCfg("Base/version");
   
    QLabel* labelCompany = new QLabel(strCompany);
    QLabel* labelToolName = new QLabel(strToolName);
    QLabel* labelVersion = new QLabel(strVersion);

    QVBoxLayout* layout = new QVBoxLayout;
    layout->addWidget(labelCompany);
    layout->addWidget(labelToolName);
    layout->addWidget(labelVersion);
    layout->setContentsMargins(50, 25, 50, 25);
    aboutWin.setLayout(layout);

    aboutWin.exec();
相关推荐
Knight_AL10 分钟前
用 JOL 验证 synchronized 的锁升级过程(偏向锁 → 轻量级锁 → 重量级锁)
开发语言·jvm·c#
啊阿狸不会拉杆35 分钟前
《数字图像处理》第 4 章 - 频域滤波
开发语言·python·数字信号处理·数字图像处理·频率域滤波
江沉晚呤时1 小时前
从零实现 C# 插件系统:轻松扩展应用功能
java·开发语言·microsoft·c#
Knight_AL1 小时前
Java 多态详解:概念、实现机制与实践应用
java·开发语言
Omigeq1 小时前
1.2.1 - 图搜索算法(以A*为例) - Python运动规划库教程(Python Motion Planning)
开发语言·python·机器人·图搜索算法
资深流水灯工程师1 小时前
基于Python的Qt开发之Pyside6 串口接收数据被分割的解决方案
开发语言·python·qt
没有bug.的程序员1 小时前
Java 并发容器深度剖析:ConcurrentHashMap 源码解析与性能优化
java·开发语言·性能优化·并发·源码解析·并发容器
量子炒饭大师2 小时前
【C++入门】零域终端的虚空指针协议——【nullptr】还在为编译器给NULL匹配为int而头疼?nullptr给予你全新的字面量!
开发语言·c++·nullptr
edisao2 小时前
一。星舰到底改变了什么?
大数据·开发语言·人工智能·科技·php
阿豪只会阿巴2 小时前
【多喝热水系列】从零开始的ROS2之旅——Day10 话题的订阅与发布1:Python
开发语言·c++·python·ubuntu·ros2