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容器目录…...
springboot 百货中心供应链管理系统小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,百货中心供应链管理系统被用户普遍使用,为方…...
【WiFi帧结构】
文章目录 帧结构MAC头部管理帧 帧结构 Wi-Fi的帧分为三部分组成:MAC头部frame bodyFCS,其中MAC是固定格式的,frame body是可变长度。 MAC头部有frame control,duration,address1,address2,addre…...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...
【电力电子】基于STM32F103C8T6单片机双极性SPWM逆变(硬件篇)
本项目是基于 STM32F103C8T6 微控制器的 SPWM(正弦脉宽调制)电源模块,能够生成可调频率和幅值的正弦波交流电源输出。该项目适用于逆变器、UPS电源、变频器等应用场景。 供电电源 输入电压采集 上图为本设计的电源电路,图中 D1 为二极管, 其目的是防止正负极电源反接, …...
第7篇:中间件全链路监控与 SQL 性能分析实践
7.1 章节导读 在构建数据库中间件的过程中,可观测性 和 性能分析 是保障系统稳定性与可维护性的核心能力。 特别是在复杂分布式场景中,必须做到: 🔍 追踪每一条 SQL 的生命周期(从入口到数据库执行)&#…...
springboot 日志类切面,接口成功记录日志,失败不记录
springboot 日志类切面,接口成功记录日志,失败不记录 自定义一个注解方法 import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;/***…...
Python 高效图像帧提取与视频编码:实战指南
Python 高效图像帧提取与视频编码:实战指南 在音视频处理领域,图像帧提取与视频编码是基础但极具挑战性的任务。Python 结合强大的第三方库(如 OpenCV、FFmpeg、PyAV),可以高效处理视频流,实现快速帧提取、压缩编码等关键功能。本文将深入介绍如何优化这些流程,提高处理…...
Visual Studio Code 扩展
Visual Studio Code 扩展 change-case 大小写转换EmmyLua for VSCode 调试插件Bookmarks 书签 change-case 大小写转换 https://marketplace.visualstudio.com/items?itemNamewmaurer.change-case 选中单词后,命令 changeCase.commands 可预览转换效果 EmmyLua…...
jdbc查询mysql数据库时,出现id顺序错误的情况
我在repository中的查询语句如下所示,即传入一个List<intager>的数据,返回这些id的问题列表。但是由于数据库查询时ID列表的顺序与预期不一致,会导致返回的id是从小到大排列的,但我不希望这样。 Query("SELECT NEW com…...
Vue3 PC端 UI组件库我更推荐Naive UI
一、Vue3生态现状与UI库选择的重要性 随着Vue3的稳定发布和Composition API的广泛采用,前端开发者面临着UI组件库的重新选择。一个好的UI库不仅能提升开发效率,还能确保项目的长期可维护性。本文将对比三大主流Vue3 UI库(Naive UI、Element …...
