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容器目录…...
深度学习在微纳光子学中的应用
深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向: 逆向设计 通过神经网络快速预测微纳结构的光学响应,替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…...
TDengine 快速体验(Docker 镜像方式)
简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能,本节首先介绍如何通过 Docker 快速体验 TDengine,然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker,请使用 安装包的方式快…...
基于当前项目通过npm包形式暴露公共组件
1.package.sjon文件配置 其中xh-flowable就是暴露出去的npm包名 2.创建tpyes文件夹,并新增内容 3.创建package文件夹...
[ICLR 2022]How Much Can CLIP Benefit Vision-and-Language Tasks?
论文网址:pdf 英文是纯手打的!论文原文的summarizing and paraphrasing。可能会出现难以避免的拼写错误和语法错误,若有发现欢迎评论指正!文章偏向于笔记,谨慎食用 目录 1. 心得 2. 论文逐段精读 2.1. Abstract 2…...
【项目实战】通过多模态+LangGraph实现PPT生成助手
PPT自动生成系统 基于LangGraph的PPT自动生成系统,可以将Markdown文档自动转换为PPT演示文稿。 功能特点 Markdown解析:自动解析Markdown文档结构PPT模板分析:分析PPT模板的布局和风格智能布局决策:匹配内容与合适的PPT布局自动…...
spring:实例工厂方法获取bean
spring处理使用静态工厂方法获取bean实例,也可以通过实例工厂方法获取bean实例。 实例工厂方法步骤如下: 定义实例工厂类(Java代码),定义实例工厂(xml),定义调用实例工厂ÿ…...
【单片机期末】单片机系统设计
主要内容:系统状态机,系统时基,系统需求分析,系统构建,系统状态流图 一、题目要求 二、绘制系统状态流图 题目:根据上述描述绘制系统状态流图,注明状态转移条件及方向。 三、利用定时器产生时…...
TRS收益互换:跨境资本流动的金融创新工具与系统化解决方案
一、TRS收益互换的本质与业务逻辑 (一)概念解析 TRS(Total Return Swap)收益互换是一种金融衍生工具,指交易双方约定在未来一定期限内,基于特定资产或指数的表现进行现金流交换的协议。其核心特征包括&am…...
04-初识css
一、css样式引入 1.1.内部样式 <div style"width: 100px;"></div>1.2.外部样式 1.2.1.外部样式1 <style>.aa {width: 100px;} </style> <div class"aa"></div>1.2.2.外部样式2 <!-- rel内表面引入的是style样…...
Linux --进程控制
本文从以下五个方面来初步认识进程控制: 目录 进程创建 进程终止 进程等待 进程替换 模拟实现一个微型shell 进程创建 在Linux系统中我们可以在一个进程使用系统调用fork()来创建子进程,创建出来的进程就是子进程,原来的进程为父进程。…...
