C 语言

关注公众号 jb51net

关闭
首页 > 软件编程 > C 语言 > Qt QSettings

Qt实现QSettings的项目实践

作者:华丽的周遭

QSettings作为Qt生态的配置管理利器,能轻松处理应用的键值对持久化,本文就来详细的介绍一下QSettings的使用,感兴趣的可以了解一下

可以这么说:QSettings是Qt生态中,跨平台持久化存储应用配置的“瑞士军刀”。

一、QSettings 是什么?

QSettings 是 Qt 提供的键值对(Key-Value)持久化存储类,用于保存应用程序的配置信息(如窗口位置、主题、网络参数、用户偏好)。其核心优势是:

二、QSettings 的底层逻辑:组织与存储

我们知道,软件的本质是:逻辑+数据。而数据的本质是:组织和存储。

1. 配置的“路径”与“组”

QSettings 用层级路径组织配置,类似文件系统的目录结构。例如:

2. 跨平台的存储位置

QSettings 会根据平台和构造参数自动选择存储位置:

平台

默认存储位置(UserScope)

系统级存储(SystemScope)

Windows​

注册表:HKEY_CURRENT_USER\Software\<Org>\<App>

注册表:HKEY_LOCAL_MACHINE\Software\<Org>\<App>

macOS​

Plist 文件:~/Library/Preferences/org.<org>.<app>.plist

Plist 文件:/Library/Preferences/org.<org>.<app>.plist

Linux​

XDG 配置目录:~/.config/<Org>/<App>.conf(优先)或 ~/.config/<Org>/<App>/<App>.conf

系统配置目录:/etc/xdg/<Org>/<App>.conf

注:若显式指定QSettings::IniFormat,则强制用 INI 文件存储(如config.ini),方便调试。

三、QSettings 的核心操作

1. 构造 QSettings 对象

QSettings 有两种常见构造方式:

(1)用“组织名+应用名”(跨平台原生存储)

#include <QSettings>

// 组织名(如公司名)、应用名(如产品名)
QSettings settings("Xilinx", "PortableMonitor");

(2)用“文件路径+格式”(显式控制存储)

// 用 INI 格式存储到当前目录的 config.ini
QSettings settings("config.ini", QSettings::IniFormat); 

// 用 NativeFormat(平台原生)存储到 /etc/myapp.conf(需 root 权限)
QSettings settings(QSettings::NativeFormat, QSettings::SystemScope, "MyOrg", "MyApp");

2. 读写配置值

QSettings 的核心是setValue()(写)和value()(读),均基于QVariant实现类型兼容。

(1)写配置:setValue(key, value)

QSettings settings("Xilinx", "PortableMonitor");

// 写基础类型
settings.setValue("Window/Width", 1920);
settings.setValue("Window/Height", 1080);
settings.setValue("Theme/DarkMode", true);

// 写 Qt 扩展类型(自动序列化)
settings.setValue("Window/Position", QPoint(100, 200));
settings.setValue("Display/ColorDepth", QColor(Qt::red));

(2)读配置:value(key, defaultValue)

QSettings settings("Xilinx", "PortableMonitor");

// 读基础类型(带默认值)
int width = settings.value("Window/Width", 1280).toInt();
int height = settings.value("Window/Height", 720).toInt();
bool darkMode = settings.value("Theme/DarkMode", false).toBool();

// 读 Qt 扩展类型
QPoint pos = settings.value("Window/Position", QPoint(0, 0)).toPoint();
QColor color = settings.value("Display/ColorDepth", QColor(Qt::black)).value<QColor>();

(3)分组管理:beginGroup()/endGroup()

用组嵌套简化键的书写(避免重复前缀):

QSettings settings("Xilinx", "PortableMonitor");

settings.beginGroup("Window");
settings.setValue("Width", 1920);   // 等价于 "Window/Width"
settings.setValue("Height", 1080);  // 等价于 "Window/Height"
settings.endGroup();                // 退出组,回到根

settings.beginGroup("Window/SubWindow"); // 嵌套组
settings.setValue("Opacity", 0.8);        // 等价于 "Window/SubWindow/Opacity"
settings.endGroup();

3. 同步与持久化:sync()

QSettings 内部有缓存(减少磁盘IO),setValue()后数据先存缓存,调用sync()才会强制写入磁盘

建议在关键配置变更后(如用户点击“保存”)或程序退出前调用:

settings.setValue("Theme/DarkMode", true);
settings.sync(); // 立即写入磁盘(可选,析构时也会自动 sync)

4. 删除配置:remove()/clear()

settings.remove("Window/Width"); // 删除 Window 组的 Width 键
settings.clear();                 // 清空所有配置(谨慎使用!)

四、支持的数据类型

QSettings 原生支持以下类型(无需额外处理):

类型

示例

转换函数

基础类型

int/bool/double/QString

toInt()/toBool()/toString()

Qt 几何类型

QPoint/QSize/QRect

toPoint()/toSize()/toRect()

Qt 样式类型

QColor/QFont/QPalette

value<QColor>()/value<QFont>()

其他

QByteArray/QStringList

toByteArray()/toStringList()

扩展:自定义类型的存储

若需存储自定义结构体,需注册元类型并实现流操作符(<</>>):

步骤1:定义结构体并注册元类型

#include <QMetaType>
#include <QDataStream>

// 自定义设备校准参数
struct CalibrationParams {
    double gainR;   // R通道增益
    double offsetB; // B通道偏移
};

// 注册元类型(需唯一名称)
Q_DECLARE_METATYPE(CalibrationParams)
qRegisterMetaType<CalibrationParams>("CalibrationParams");

步骤2:实现流操作符(序列化/反序列化)

// 序列化(写入QDataStream)
QDataStream &operator<<(QDataStream &out, const CalibrationParams &params) {
    out << params.gainR << params.offsetB;
    return out;
}

// 反序列化(从QDataStream读取)
QDataStream &operator>>(QDataStream &in, CalibrationParams &params) {
    in >> params.gainR >> params.offsetB;
    return in;
}

// 注册流操作符(让QSettings识别)
qRegisterMetaTypeStreamOperators<CalibrationParams>("CalibrationParams");

步骤3:读写自定义类型

// 写自定义类型
CalibrationParams params{1.2, -0.5};
settings.setValue("Device/Calibration", QVariant::fromValue(params));

// 读自定义类型
QVariant var = settings.value("Device/Calibration");
if (var.canConvert<CalibrationParams>()) {
    CalibrationParams p = var.value<CalibrationParams>();
    qDebug() << "GainR:" << p.gainR << "OffsetB:" << p.offsetB;
}

五、高级技巧

1. 显式指定格式与范围

构造时可指定存储格式Format)和作用域Scope):

// 格式:IniFormat(通用INI)/ NativeFormat(平台原生)/ InvalidFormat
// 范围:UserScope(当前用户)/ SystemScope(所有用户)
QSettings settings(
    QSettings::IniFormat,    // 用INI文件
    QSettings::UserScope,    // 当前用户
    "Xilinx",                // 组织名
    "PortableMonitor"        // 应用名
);

INI 格式示例PortableMonitor.ini):

[Window]
Width=1920
Height=1080
[Theme]
DarkMode=true

2. 获取所有配置键/组

QSettings settings("Xilinx", "PortableMonitor");
QStringList allKeys = settings.allKeys();
QStringList groups = settings.childGroups(); // 根组下的所有组

3. 监听配置变化(实时更新)

QSettings本身无信号,但可通过QFileSystemWatcher监控配置文件的变化(适用于INI格式):

#include <QFileSystemWatcher>

QSettings settings("config.ini", QSettings::IniFormat);
QFileSystemWatcher watcher;
watcher.addPath("config.ini"); // 监控配置文件

// 连接信号:文件变化时重新加载配置
connect(&watcher, &QFileSystemWatcher::fileChanged, [&](const QString &path) {
    settings.sync(); // 重新读取磁盘上的最新配置
    loadConfig();    // 自定义函数:重新应用配置
});

4. 线程安全

QSettings 是可重入(Reentrant)非线程安全(Thread-Safe)的——多线程同时读写会导致数据竞争。需用互斥锁(QMutex保护:

QMutex mutex;
QSettings settings("Xilinx", "PortableMonitor");
// 写操作加锁
mutex.lock();
settings.setValue("Theme/DarkMode", true);
settings.sync();
mutex.unlock();
// 读操作加锁
mutex.lock();
bool darkMode = settings.value("Theme/DarkMode", false).toBool();
mutex.unlock();

六、注意事项

七、实战示例:产品配置存储

假设你的产品需要保存窗口状态视频输入源色彩校正参数,代码如下:

// 定义配置键(常量,避免硬编码)
namespace ConfigKeys {
    const QString WindowGroup = "Window";
    const QString WindowSize = WindowGroup + "/Size";
    const QString WindowPos = WindowGroup + "/Pos";
    const QString VideoGroup = "Video";
    const QString InputSource = VideoGroup + "/InputSource"; // HDMI/SDI/VGA
    const QString ColorGroup = "Color";
    const QString Brightness = ColorGroup + "/Brightness";
    const QString Contrast = ColorGroup + "/Contrast";
}
// 保存配置
void saveSettings(MainWindow *win, VideoInput input, ColorParams color) {
    QSettings settings("Xilinx", "PortableMonitor");
    // 窗口状态
    settings.beginGroup(ConfigKeys::WindowGroup);
    settings.setValue("Size", win->size());
    settings.setValue("Pos", win->pos());
    settings.endGroup();
    // 视频输入源
    settings.beginGroup(ConfigKeys::VideoGroup);
    settings.setValue("InputSource", static_cast<int>(input)); // 枚举转int
    settings.endGroup();
    // 色彩参数
    settings.beginGroup(ConfigKeys::ColorGroup);
    settings.setValue("Brightness", color.brightness);
    settings.setValue("Contrast", color.contrast);
    settings.endGroup();
    settings.sync(); // 强制写入
}
// 加载配置
void loadSettings(MainWindow *win, VideoInput *input, ColorParams *color) {
    QSettings settings("Xilinx", "PortableMonitor");
    // 窗口状态
    settings.beginGroup(ConfigKeys::WindowGroup);
    QSize size = settings.value("Size", QSize(1280, 720)).toSize();
    QPoint pos = settings.value("Pos", QPoint(0, 0)).toPoint();
    settings.endGroup();
    win->resize(size);
    win->move(pos);
    // 视频输入源
    settings.beginGroup(ConfigKeys::VideoGroup);
    *input = static_cast<VideoInput>(settings.value("InputSource", 0).toInt()); // 默认HDMI
    settings.endGroup();
    // 色彩参数
    settings.beginGroup(ConfigKeys::ColorGroup);
    color->brightness = settings.value("Brightness", 50).toInt(); // 默认50%
    color->contrast = settings.value("Contrast", 50).toInt();
    settings.endGroup();
}

八、总结

QSettings 是配置持久化的首选方案——它帮你屏蔽了跨平台差异,用简单的键值对管理复杂配置。

到此这篇关于Qt实现QSettings的项目实践的文章就介绍到这了,更多相关Qt QSettings内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文