Qt 中实现系统主题感知
【写在前面】
在现代桌面应用程序开发中,系统主题感知是一项重要的功能,它使得应用程序能够根据用户的系统主题设置(如深色模式或浅色模式)自动调整其外观。
Qt 作为一个跨平台的C++图形用户界面应用程序开发框架,提供了丰富的工具和类来实现这一功能。
【正文开始】
一、使用效果
二、系统主题感知助手类(SystemThemeHelper)
SystemThemeHelper
类是一个封装了系统主题感知功能的Qt对象。它主要通过读取系统设置和监听系统主题变化来更新应用程序的主题颜色和颜色方案。
-
类定义与属性
在
systemthemehelper.h
中,SystemThemeHelper
类继承自QObject
,并定义了两个属性:themeColor
和colorScheme
。这两个属性分别表示当前的主题颜色和颜色方案(深色、浅色或无)。class SystemThemeHelper : public QObject {Q_OBJECTQ_PROPERTY(QColor themeColor READ themeColor NOTIFY themeColorChanged)Q_PROPERTY(SystemThemeHelper::ColorScheme colorScheme READ colorScheme NOTIFY colorSchemeChanged)// ... };
ColorScheme
是一个枚举类,定义了三种颜色方案:None
、Dark
和Light
。 -
构造函数与析构函数
SystemThemeHelper
的构造函数初始化了一些私有成员变量,并启动了一个定时器,用于定期更新主题颜色和颜色方案。析构函数则负责清理资源。SystemThemeHelper::SystemThemeHelper(QObject *parent): QObject{parent}, d_ptr(new SystemThemeHelperPrivate(this)) {Q_D(SystemThemeHelper);d->m_themeColor = getThemeColor();d->m_colorScheme = getColorScheme();d->m_timer.start(200, this);#ifdef Q_OS_WINinitializeFunctionPointers();#endif }SystemThemeHelper::~SystemThemeHelper() {// 清理资源 }
-
获取主题颜色和颜色方案
getThemeColor
和getColorScheme
是两个不可用于绑定的方法,它们立即返回当前的主题颜色和颜色方案,但不会触发任何更新通知。这两个方法主要用于快速获取当前设置,而不关心后续的变化。QColor SystemThemeHelper::getThemeColor() const {Q_D(const SystemThemeHelper);#ifdef Q_OS_WINreturn QColor::fromRgb(d->m_themeColorSettings.value("ColorizationColor").toUInt());#endif }SystemThemeHelper::ColorScheme SystemThemeHelper::getColorScheme() const {Q_D(const SystemThemeHelper);#if QT_VERSION >= QT_VERSION_CHECK(6, 5, 0)const auto scheme = QGuiApplication::styleHints()->colorScheme();return scheme == Qt::ColorScheme::Dark ? ColorScheme::Dark : ColorScheme::Light;#else#ifdef Q_OS_WINreturn !d->m_colorSchemeSettings.value("AppsUseLightTheme").toBool() ? ColorScheme::Dark : ColorScheme::Light;#else //linuxconst QPalette defaultPalette;const auto text = defaultPalette.color(QPalette::WindowText);const auto window = defaultPalette.color(QPalette::Window);return text.lightness() > window.lightness() ? ColorScheme::Dark : ColorScheme::Light;#endif // Q_OS_WIN#endif // QT_VERSION }
-
更新主题颜色和颜色方案
themeColor
和colorScheme
是两个可用于绑定的方法,它们返回当前的主题颜色和颜色方案,并在值发生变化时发出通知。这两个方法内部调用了私有成员函数的更新逻辑。QColor SystemThemeHelper::themeColor() {Q_D(SystemThemeHelper);d->_updateThemeColor();return d->m_themeColor; }SystemThemeHelper::ColorScheme SystemThemeHelper::colorScheme() {Q_D(SystemThemeHelper);d->_updateColorScheme();return d->m_colorScheme; }
-
设置窗口标题栏模式
setWindowTitleBarMode
方法允许设置窗口标题栏的模式(深色或浅色)。这个方法在Windows平台上通过调用DWM API
实现,而在其他平台上则不支持。bool SystemThemeHelper::setWindowTitleBarMode(QWindow *window, bool isDark) {#ifdef Q_OS_WINreturn bool(pDwmSetWindowAttribute ? !pDwmSetWindowAttribute(HWND(window->winId()), 20, &isDark, sizeof(BOOL)) : false);#elsereturn false;#endif //Q_OS_WIN }
-
定时器事件处理
timerEvent
方法是一个虚函数,用于处理定时器事件。它定期调用更新函数来检查主题颜色和颜色方案是否发生变化,并在变化时发出通知。void SystemThemeHelper::timerEvent(QTimerEvent *) {Q_D(SystemThemeHelper);d->_updateThemeColor();d->_updateColorScheme(); }
三、实现细节
SystemThemeHelperPrivate
是SystemThemeHelper
的私有实现类,它封装了所有的实现细节和状态变量。这个类主要负责读取系统设置、更新主题颜色和颜色方案,并发出通知。
-
构造函数与成员变量
SystemThemeHelperPrivate
的构造函数接收一个指向SystemThemeHelper
的指针,并初始化成员变量。成员变量包括主题颜色、颜色方案、定时器和一些平台特定的设置对象。SystemThemeHelperPrivate::SystemThemeHelperPrivate(SystemThemeHelper *q): q_ptr(q) {// 初始化成员变量 }
-
更新函数
_updateThemeColor
和_updateColorScheme
是两个更新函数,它们检查当前的主题颜色和颜色方案是否发生变化,并在变化时更新成员变量并发出通知。void SystemThemeHelperPrivate::_updateThemeColor() {Q_Q(SystemThemeHelper);auto nowThemeColor = q->getThemeColor();if (nowThemeColor != m_themeColor) {m_themeColor = nowThemeColor;emit q->themeColorChanged();} }void SystemThemeHelperPrivate::_updateColorScheme() {Q_Q(SystemThemeHelper);auto nowColorScheme = q->getColorScheme();if (nowColorScheme != m_colorScheme) {m_colorScheme = nowColorScheme;emit q->colorSchemeChanged();} }
-
平台特定的实现
在Windows平台上,
SystemThemeHelperPrivate
使用QSettings
来读取系统主题设置,并使用DWM API来设置窗口标题栏的模式。这些实现细节被封装在条件编译块中,以确保跨平台的兼容性。#ifdef Q_OS_WIN QSettings m_themeColorSettings{QSettings::UserScope, "Microsoft", "Windows\\DWM"}; QSettings m_colorSchemeSettings{QSettings::UserScope, "Microsoft", "Windows\\CurrentVersion\\Themes\\Personalize"}; static DwmSetWindowAttributeFunc pDwmSetWindowAttribute = nullptr; // ... static inline bool initializeFunctionPointers() {// 初始化DWM API函数指针 } #endif //Q_OS_WIN
四、如何使用
C++:
SystemThemeHelper *helper = new SystemThemeHelper;QObject::connect(helper, &SystemThemeHelper::themeColorChanged, [helper]{qDebug() << helper->getThemeColor();});QObject::connect(helper, &SystemThemeHelper::colorSchemeChanged, [helper]{qDebug() << helper->getColorScheme();});
Qml:
import QtQuick 2.15
import QtQuick.Window 2.15import DelegateUI.Utils 1.0Window {id: windowwidth: 640height: 480visible: truetitle: qsTr("SystemThemeHelper Test - ") + (themeHelper.colorScheme == SystemThemeHelper.Dark ? "Dark" : "Light")color: themeHelper.colorScheme == SystemThemeHelper.Dark ? "black" : "white"Behavior on color { ColorAnimation { } }SystemThemeHelper {id: themeHelperonThemeColorChanged: {console.log("onThemeColorChanged:", themeColor);}onColorSchemeChanged: {setWindowTitleBarMode(window, themeHelper.colorScheme == SystemThemeHelper.Dark)console.log("onColorSchemeChanged:", colorScheme);}Component.onCompleted: {console.log("onColorSchemeChanged:", colorScheme);setWindowTitleBarMode(window, themeHelper.colorScheme == SystemThemeHelper.Dark)}}Text {anchors.centerIn: parenttext: qsTr("主题颜色")font.family: "微软雅黑"font.pointSize: 32color: themeHelper.themeColor}
}
【结语】
通过SystemThemeHelper
类,我们可以在 Qt 应用程序中实现系统主题感知功能。
这个类封装了读取系统设置、更新主题颜色和颜色方案以及发出通知的逻辑,使得我们可以轻松地根据系统主题变化来调整应用程序的外观。
此外,通过条件编译和平台特定的实现,还确保了跨平台的兼容性。
最后:项目链接(多多star呀…⭐_⭐):
Github: https://github.com/mengps/QmlControls
Gitee: https://gitee.com/MenPenS/QmlControls
相关文章:

Qt 中实现系统主题感知
【写在前面】 在现代桌面应用程序开发中,系统主题感知是一项重要的功能,它使得应用程序能够根据用户的系统主题设置(如深色模式或浅色模式)自动调整其外观。 Qt 作为一个跨平台的C图形用户界面应用程序开发框架,提供…...
Modbus TCP 报文说明
Modbus TCP 报文说明 Modbus TCP 报文结构报文解析功能码说明Modbus 功能码与 PLC 地址的对应关系 Modbus TCP 报文结构 事务标识符(Transaction Identifier,2 字节): 用于匹配请求和响应,通常由客户端生成࿰…...

音视频入门基础:MPEG2-TS专题(24)——FFmpeg源码中,显示TS流每个packet的pts、dts的实现
音视频入门基础:MPEG2-TS专题系列文章: 音视频入门基础:MPEG2-TS专题(1)——MPEG2-TS官方文档下载 音视频入门基础:MPEG2-TS专题(2)——使用FFmpeg命令生成ts文件 音视频入门基础…...
大模型:OneFitsAll、Time - LLM、LLaTA
LLM数据集:ETT、Illness、Weather ETT、Illness、Weather在上述提到的论文中都是用于时间序列预测研究的真实世界数据集,以下是对它们的具体介绍: ETT数据集 内容:ETT是电力变压器温度(Electric Transformer Temperature)数据集,通常包含电力变压器在不同时间点的温度…...

连锁餐饮行业数据可视化分析方案
引言 随着连锁餐饮行业的迅速发展,市场竞争日益激烈。企业需要更加精准地把握运营状况、消费者需求和市场趋势,以制定科学合理的决策,提升竞争力和盈利能力。可视化数据分析可以帮助连锁餐饮企业整合多源数据,通过直观、动态的可…...

Ubuntu 下使用命令行将 U 盘格式化为 ext4、FAT32 和 exFAT 的详细教程
Ubuntu 下使用命令行将 U 盘格式化为 ext4、FAT32 和 exFAT 的详细教程 作者:Witheart更新时间:20241228 本教程将详细介绍如何将 U 盘格式化为 ext4、FAT32 和 exFAT 文件系统,同时包括如何安装必要工具(如 exfat-utils&#x…...
多说话人ASR的衡量指标和有效计算工具包
WER (Word Error Rate) 定义:预测的识别语音序列于groundtruth抄本之间的编辑距离 除以 ground truth抄本的单词数量 编辑距离 (预测的识别语音序列,groundtruth 抄本)/ ground truth抄本的单词数量 英文定义:It is g…...
英伟达(NVIDIA)
本文来自智谱清言 ------------------------------ 英伟达(NVIDIA)是一家成立于1993年的美国跨国科技公司,由黄仁勋、克里斯马拉科夫斯基和柯蒂斯普里姆共同创立。公司总部位于加利福尼亚州圣克拉拉市。英伟达最初专注于图形芯片的设计&…...
【环境配置】Jupyter Notebook切换虚拟环境
在Jupyter Notebook中是可以切换虚拟环境的,以下是几种常见的方法: 方法一:使用nb_conda_kernels扩展(适用于Anaconda环境) 安装 如果你使用的是Anaconda环境,首先确保你已经安装了 nb_conda 包。如果没…...

嵌入式单片机窗口看门狗控制与实现
窗口看门狗 注意:WWDG外设没有独立的时钟源,而是挂载在APB1总线下,APB1总线外设时钟为42MHZ。 了解WWDG外设的使用流程,可以参考stm32f4xx_wwdg.c的开头注释,具体流程如下图所示...

NiChart 多模态神经影像(structural MRI,functional MRI,and diffusion MRI)处理和分析工具包安装
NiChart多模态神经影像部署 NiChart 本地安装Git clone 问题personal access token PAT 问题 NiChart 云端注册AWS验证问题 NiChart 是UPenn大学,Christos Davatzikos教授开发的一个多模态MRI影像,structural (sMRI), diffusion (dMRI), and …...
Es搭建——单节点——Linux
Es搭建——单节点——Linux 一、安装 下载安装包: 官网下载地址:https://www.elastic.co/downloads/elasticsearch 上传包到linux 切换到安装目录下 解压:tar -zxvf elasticsearch-7.17.1-linux-x86_64.tar.gz 重命名安装文件夹 mv elastics…...
Python自动化测试之线上流量回放:录制、打标、压测与平台选择
在自动化测试中,线上流量回放是一项关键技术,可以模拟真实用户的请求并重现线上场景,验证系统的性能和稳定性。本文将介绍Python自动化测试中的线上流量回放技术,并提供实战代码,帮助你了解流量的录制、打标、压测发起…...

k-Means聚类算法 HNUST【数据分析技术】(2025)
1.理论知识 K-means算法,又称为k均值算法。K-means算法中的k表示的是聚类为k个簇,means代表取每一个聚类中数据值的均值作为该簇的中心,或者称为质心,即用每一个的类的质心对该簇进行描述。K-Means算法接受参数K;然后将…...

STM32学习之 按键/光敏电阻 控制 LED/蜂鸣器
STM32学习之 按键/光敏电阻 控制 LED/蜂鸣器 1、按键控制 LED 按键:常见的输入设备,按下导通,松手断开 按键抖动:由子按键内部使用的是机械式弹簧片来进行通断的、所以在按下和松手的瞬间会伴随有一连串的抖动 按键控制LED接线图: 要有工程…...
VUE前端实现防抖节流 Lodash
方法一:采用Lodash工具库 Lodash 是一个一致性、模块化、高性能的 JavaScript 实用工具库。 (1)采用终端导入Lodash库 $ npm i -g npm $ npm i --save lodash (2)应用 示例:搜索框输入防抖 在这个示例…...

Ubuntu20.04 交叉编译Qt5.15.15 for rk3588
rk3588编译Qt搞了我大半年了,一直困惑特别鸣谢:qq1033878279的网友远程帮我编译演示了一遍。 一、vmware 安装基础工具 sudo apt install -y build-essential net-tools openssh-server vim openssl libssl-dev 二、vmware 下载 cmake和Qt源码 下载cm…...

Unity编译Android apk包进度奇慢或gradle报错的解决方案
最近遇到Unity编译Android apk进度卡在"Calling IPostGenerateGradleAndroidProject callbacks"进度一直不变,如下图: 最后提示编译失败,类似错误如下: Picked up JAVA_TOOL_OPTIONS: -Dfile.encodingUTF-8FAILURE: Bu…...

【Qt】多元素控件:QListWidget、QTableWidget、QTreeWidget
目录 QListWidget 核心属性: 核心方法: 核心信号: 例子: QListWidgetItem QTableWidget 核心方法: 核心信号 QTableWidgetItem 例子: QTreeWidget 核心方法: 核心信号:…...

Docker基础知识 Docker命令、镜像、容器、数据卷、自定义镜像、使用Docker部署Java应用、部署前端代码、DockerCompose一键部署
目录 1.Docker 2.镜像和容器 2.1 定义 2.2 开机自动启动容器 3.docker命令 3.1 docker run 参数说明 3.2 常见命令 3.3 命令演示 3.4 命令别名 4.Docker命令详解 5.数据卷 5.1 定义 5.2 数据卷的相关命令 5.3 数据卷命令 5.4 挂载本地目录或文件 5.4.1 定义 5.4.2 mysql容器目录…...

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型
摘要 拍照搜题系统采用“三层管道(多模态 OCR → 语义检索 → 答案渲染)、两级检索(倒排 BM25 向量 HNSW)并以大语言模型兜底”的整体框架: 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后,分别用…...

深度学习在微纳光子学中的应用
深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向: 逆向设计 通过神经网络快速预测微纳结构的光学响应,替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…...
【杂谈】-递归进化:人工智能的自我改进与监管挑战
递归进化:人工智能的自我改进与监管挑战 文章目录 递归进化:人工智能的自我改进与监管挑战1、自我改进型人工智能的崛起2、人工智能如何挑战人类监管?3、确保人工智能受控的策略4、人类在人工智能发展中的角色5、平衡自主性与控制力6、总结与…...

Linux 文件类型,目录与路径,文件与目录管理
文件类型 后面的字符表示文件类型标志 普通文件:-(纯文本文件,二进制文件,数据格式文件) 如文本文件、图片、程序文件等。 目录文件:d(directory) 用来存放其他文件或子目录。 设备…...

Spark 之 入门讲解详细版(1)
1、简介 1.1 Spark简介 Spark是加州大学伯克利分校AMP实验室(Algorithms, Machines, and People Lab)开发通用内存并行计算框架。Spark在2013年6月进入Apache成为孵化项目,8个月后成为Apache顶级项目,速度之快足见过人之处&…...
脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)
一、数据处理与分析实战 (一)实时滤波与参数调整 基础滤波操作 60Hz 工频滤波:勾选界面右侧 “60Hz” 复选框,可有效抑制电网干扰(适用于北美地区,欧洲用户可调整为 50Hz)。 平滑处理&…...

剑指offer20_链表中环的入口节点
链表中环的入口节点 给定一个链表,若其中包含环,则输出环的入口节点。 若其中不包含环,则输出null。 数据范围 节点 val 值取值范围 [ 1 , 1000 ] [1,1000] [1,1000]。 节点 val 值各不相同。 链表长度 [ 0 , 500 ] [0,500] [0,500]。 …...

mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包
文章目录 现象:mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包遇到 rpm 命令找不到已经安装的 MySQL 包时,可能是因为以下几个原因:1.MySQL 不是通过 RPM 包安装的2.RPM 数据库损坏3.使用了不同的包名或路径4.使用其他包…...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...
Redis的发布订阅模式与专业的 MQ(如 Kafka, RabbitMQ)相比,优缺点是什么?适用于哪些场景?
Redis 的发布订阅(Pub/Sub)模式与专业的 MQ(Message Queue)如 Kafka、RabbitMQ 进行比较,核心的权衡点在于:简单与速度 vs. 可靠与功能。 下面我们详细展开对比。 Redis Pub/Sub 的核心特点 它是一个发后…...