当前位置: 首页 > news >正文

CMake实战篇1-主题管理库

CMake实战篇1-主题管理库

CMake实战篇1-主题管理库

目录
  • CMake实战篇1-主题管理库
    • 一、核心用法:开箱即用的主题管理
      • 1.1 快速集成
      • 1.2 简单调用
      • 1.3 效果预览
    • 二、核心优势:适配多场景的复用价值
      • 2.1 跨项目复用,提效降本
      • 2.2 跨平台兼容,适配性强
      • 2.3 接口简洁,低学习成本
      • 2.4 灵活扩展,适配个性化需求
    • 三、使用注意事项与不足
      • 3.1 运行时依赖
      • 3.2 样式表冲突风险
      • 3.3 调试难度略增
      • 3.4 功能轻量化,适配场景有限
    • 四、总结
    • 五.源码实现


《宿建德江》· 孟浩然

移舟泊烟渚,日暮客愁新。
野旷天低树,江清月近人。

33

在多 Qt 项目开发场景中,重复开发主题切换功能不仅耗时,还易导致代码不一致。为此,我们基于 CMake 构建了一款可直接复用的 Qt 主题管理器动态库,无需重复造轮子,让多个项目快速具备动态主题切换能力。

本文由 豆包AI 协助完成

一、核心用法:开箱即用的主题管理

这款动态库的设计核心是 “极简接入、灵活使用”,无需深入理解底层实现,仅需两步即可集成到任意 Qt 项目中。

1.1 快速集成

将编译好的动态库文件(Windows 下为.dll/.lib,Linux 下为.so,macOS 下为.dylib)和头文件拷贝到项目指定目录,在项目的 CMakeLists.txt 中仅需几行配置即可完成依赖引入:

find_package(UThemeManager REQUIRED)
target_link_libraries(${PROJECT_NAME} PRIVATE Hakuon::UThemeManager)

1.2 简单调用

在项目代码中,通过全局单例即可实现主题切换,无需额外初始化,核心调用仅需一行代码:

void UThemeManager::applyTheme(UThemeManager::ETheme theme)
{QString typeName;switch (theme){case ET_DarkBlue:typeName = "darkblue";break;case ET_Light:typeName = "lightblue";break;default:break;}applyTheme(QString(":/res/%1.qss").arg(typeName));
}

1.3 效果预览

t_1

二、核心优势:适配多场景的复用价值

2.1 跨项目复用,提效降本

将主题管理逻辑抽离为独立动态库,所有 Qt 项目无需重复编写样式表加载、主题切换代码,接入成本仅需几分钟,大幅减少重复开发工作量,且能保证所有项目的主题切换逻辑一致。

2.2 跨平台兼容,适配性强

基于 CMake 构建,天然支持 Windows、Linux、macOS 三大平台编译,编译产物可直接在对应平台使用,无需针对不同系统做额外适配,降低跨平台开发复杂度。

2.3 接口简洁,低学习成本

仅暴露核心的主题切换、自定义样式加载接口,无需掌握复杂的配置规则,即使是新手也能快速上手,且单例模式设计符合 Qt 项目的全局使用习惯。

2.4 灵活扩展,适配个性化需求

支持加载自定义 QSS 文件,不仅局限于内置的亮色 / 暗色主题,可根据不同项目的视觉风格,灵活接入专属主题样式,满足个性化需求。

三、使用注意事项与不足

3.1 运行时依赖

动态库需与项目运行环境匹配(如 Qt 版本、编译器、系统架构),若项目更换 Qt 版本或编译环境,需重新编译动态库,否则可能出现兼容性问题。

3.2 样式表冲突风险

若项目自身已设置局部样式表,可能与主题管理器的全局样式表产生冲突,需在使用时做好样式表的层级规划,避免样式覆盖异常。

3.3 调试难度略增

相较于项目内的本地代码,动态库的调试需要依赖调试符号文件(如 Windows 下的 PDB 文件),若缺失则难以定位库内的问题,增加调试成本。

3.4 功能轻量化,适配场景有限

当前版本仅聚焦核心的主题切换能力,未支持主题变量、多主题预览、样式缓存等进阶功能,若项目有复杂的主题管理需求,需在此基础上扩展。

四、总结

这款基于 CMake 的 Qt 主题管理器动态库,以 “复用” 为核心,解决了多 Qt 项目主题切换逻辑冗余的问题,凭借简洁的接入方式和跨平台特性,能快速落地到各类 Qt 项目中。虽然存在少量使用限制,但通过规范使用流程(如统一 Qt 编译环境、规划样式表层级)可有效规避,是提升多 Qt 项目开发效率的实用工具。

五.源码实现

#ifndef UTHEMEMANAGER_H
#define UTHEMEMANAGER_H/*! ===================================================================@class      UThemeManager;@brief      用于主题管理, 支持不同的主题皮肤;@note       note;@author     Hakuon@date       2025-11-20
======================================================================*/#include <QObject>
#include <QtCore/qglobal.h>#ifndef BUILD_STATIC
# if defined(UTHEMEMANAGER_LIBRARY)
#  define UTHEMEMANAGER_EXPORT Q_DECL_EXPORT
# else
#  define UTHEMEMANAGER_EXPORT Q_DECL_IMPORT
# endif
#else
# define HAKUWIDGETS_EXPORT
#endifclass UTHEMEMANAGER_EXPORT UThemeManager
{
public:enum ETheme {ET_DarkBlue = 0,ET_Light,ET_None     = 100,};~UThemeManager();static UThemeManager* instance();void applyTheme(ETheme theme = ET_DarkBlue);void applyTheme(const QString& path);public:explicit UThemeManager();
};#endif // UTHEMEMANAGER_H
#include "UThemeManager.h"#include <QApplication>
#include <QDebug>
#include <QFile>UThemeManager::UThemeManager()
{
}UThemeManager::~UThemeManager()
{
}UThemeManager *UThemeManager::instance()
{static UThemeManager s_utm_inst;return &s_utm_inst;
}void UThemeManager::applyTheme(UThemeManager::ETheme theme)
{QString typeName;switch (theme){case ET_DarkBlue:typeName = "darkblue";break;case ET_Light:typeName = "lightblue";break;default:break;}applyTheme(QString(":/res/%1.qss").arg(typeName));
}void UThemeManager::applyTheme(const QString &path)
{QFile file(path);if (file.open(QIODevice::Text | QIODevice::ReadOnly)){qApp->setStyleSheet(file.readAll());}file.close();qDebug() << ((file.exists()) ? u8"加载主题管理器成功. ^_^" : u8"主题文件未找到. 加载失败 >_<");
}

CMakeLists.txt文件编写

cmake_minimum_required(VERSION 3.15)# ------------------------------------
# 设置项目的基本信息
# ------------------------------------
project(UThemeManagerVERSION     1.0.0LANGUAGES   CXXDESCRIPTION "A Custom Theme Manager"
)# -------------------------------------------------
function(group_files_by_folder out_var folder_path file_glob_pattern group_name)file(GLOB FILE_LIST "${folder_path}/${file_glob_pattern}")if(FILE_LIST)source_group("${group_name}" FILES ${FILE_LIST})set(${out_var} ${FILE_LIST} PARENT_SCOPE)endif()
endfunction()
# -------------------------------------------------# ------------------------------------
# 文件分组
# ------------------------------------
group_files_by_folder(HEADERS ${CMAKE_CURRENT_SOURCE_DIR} "*.h"   "Include")
group_files_by_folder(SOURCES ${CMAKE_CURRENT_SOURCE_DIR} "*.cpp" "Src")
group_files_by_folder(RES     ${CMAKE_CURRENT_SOURCE_DIR} "*.qrc" "res")set(EXPORT_HEADERSUThemeManager.h
)# ------------------------------------
# 生成库
# ------------------------------------
add_library(${PROJECT_NAME} SHARED ${HEADERS} ${SOURCES} ${RES})# ------------------------------------
# 区分构建和install后的头文件引用
# ------------------------------------
target_include_directories(${PROJECT_NAME}PUBLIC$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>$<INSTALL_INTERFACE:include/${PROJECT_NAME}>
)set_target_properties(${PROJECT_NAME} PROPERTIESDEBUG_POSTFIX               "d"PUBLIC_HEADER               "${EXPORT_HEADERS}"AUTORCC                     ONAUTOUIC                     ONAUTOMOC                     ON
)target_compile_definitions(${PROJECT_NAME} PRIVATE UTHEMEMANAGER_LIBRARY)find_package(Qt5 COMPONENTS Core Widgets REQUIRED)
target_link_libraries(${PROJECT_NAME} PUBLIC Qt5::Core Qt5::Widgets)# ------------------------------------
# 安装属性
# ------------------------------------
include(GNUInstallDirs)
include(CMakePackageConfigHelpers)# 安装目标文件
install(TARGETS ${PROJECT_NAME}EXPORT ${PROJECT_NAME}TargetsPUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}RUNTIME       DESTINATION ${CMAKE_INSTALL_BINDIR}LIBRARY       DESTINATION ${CMAKE_INSTALL_LIBDIR}ARCHIVE       DESTINATION ${CMAKE_INSTALL_LIBDIR}
)# 导出目标信息
install(EXPORT ${PROJECT_NAME}TargetsFILE ${PROJECT_NAME}Targets.cmakeNAMESPACE Hakuon::DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}
)# 生成配置文件
configure_package_config_file("${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}Config.cmake.in""${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}
)write_basic_package_version_file("${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake"VERSION ${PROJECT_VERSION}COMPATIBILITY SameMajorVersion
)# 安装 config 文件
install(FILES"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake""${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake"DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}
)

UThemeManagerConfig.cmake.in编写

# @PACKAGE_INIT@ 必须放在开头
@PACKAGE_INIT@# 设置版本变量(可选但推荐), set(MyMath_VERSION 2.3.1)
set(@PROJECT_NAME@_VERSION @PROJECT_VERSION@)# 包含目标文件(核心), 一般值得是 lib\cmake\MyMath
include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake")# 提供传统变量(向后兼容),set(MyMath_LIBRARIES MyMath::MyMath)
set(@PROJECT_NAME@_LIBRARIES @PROJECT_NAME@::@PROJECT_NAME@)# 检查必需组件(如果有)
check_required_components(@PROJECT_NAME@)
http://www.jsqmd.com/news/89678/

相关文章:

  • TS-Loader 源码解析与自定义 Webpack Loader 开发指南
  • uos server 1070e部署OpenStack基础篇-上篇
  • OpenCore Legacy Patcher终极指南:让老旧Mac重获新生的完整教程
  • Windows Defender终极移除指南:彻底释放系统性能的完整方案
  • 【PBFT算法】
  • 对等保2.0的理解
  • C++的第十五天笔记
  • MouseTester:专业鼠标性能测试工具完整指南
  • [Linux] 手写轻量C++函数性能探查器:CPU占用率耗时
  • MsgViewer:解锁邮件查看新体验的跨平台神器
  • 突破极限!让Umi-OCR在Windows 7上重获新生的完美方案
  • 函数指针与指针函数
  • 固定Shape场景下Ascend C算子Tiling实现详解
  • 从零部署 OpenKM 文档管理系统:企业级文档管理实战指南
  • docker容器通过host.docker.internal访问宿主机的注意事项
  • [dx12显示图片] ImGui Learn Data Day 3
  • Nugget下载工具完整指南:极简高效的命令行文件获取方案
  • GridPlayer多视频同步播放器:新手快速上手指南
  • iStore插件中心终极指南:OpenWRT新手轻松安装与管理插件
  • 【PoW算法】
  • 原神帧率同步机制深度解析与性能优化实践
  • springboot整合kafka connect
  • 【专业指南】BetterNCM安装器完整教程:如何轻松管理网易云音乐插件生态
  • 智能防走失定位工具,核心功能,绑定家人手机,实时查看位置,设置安全区域,如小区,超出区域自动提醒,支持一键求救,应用场景,预防老人痴呆患者走失,家人随时掌握位置,放心又安心。
  • 【大模型预训练】19-分布式集群架构:GPU、TPU集群的拓扑结构与通信优化
  • 【ZAB协议】
  • 告别单选困境:Layui多选下拉框的优雅解决方案
  • tinySubFinder字幕下载
  • 基于SSM的在线药品销售系统【源码+文档+调试】
  • Mammoth.js实战指南:轻松实现Word转HTML的完整解决方案