基于Qt实现系统主题感知功能

 更新时间:2024年12月29日 08:31:56   作者:梦起丶  
在现代桌面应用程序开发中,系统主题感知是一项重要的功能,它使得应用程序能够根据用户的系统主题设置(如深色模式或浅色模式)自动调整其外观,Qt 作为一个跨平台的C++图形用户界面应用程序开发框架,提供了丰富的工具和类来实现这一功能,需要的朋友可以参考下

【正文开始】

一、使用效果

二、系统主题感知助手类(SystemThemeHelper)

SystemThemeHelper类是一个封装了系统主题感知功能的Qt对象。它主要通过读取系统设置和监听系统主题变化来更新应用程序的主题颜色和颜色方案。

  • 类定义与属性

    systemthemehelper.h中,SystemThemeHelper类继承自QObject,并定义了两个属性:themeColorcolorScheme。这两个属性分别表示当前的主题颜色和颜色方案(深色、浅色或无)。

class SystemThemeHelper : public QObject
{
    Q_OBJECT
    Q_PROPERTY(QColor themeColor READ themeColor NOTIFY themeColorChanged)
    Q_PROPERTY(SystemThemeHelper::ColorScheme colorScheme READ colorScheme NOTIFY colorSchemeChanged)
    // ...
};
  • ColorScheme是一个枚举类,定义了三种颜色方案:NoneDarkLight

  • 构造函数与析构函数

    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_WIN
    initializeFunctionPointers();
    #endif
}

SystemThemeHelper::~SystemThemeHelper()
{
    // 清理资源
}

获取主题颜色和颜色方案

getThemeColorgetColorScheme是两个不可用于绑定的方法,它们立即返回当前的主题颜色和颜色方案,但不会触发任何更新通知。这两个方法主要用于快速获取当前设置,而不关心后续的变化。

QColor SystemThemeHelper::getThemeColor() const
{
    Q_D(const SystemThemeHelper);
    #ifdef Q_OS_WIN
    return 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_WIN
    return !d->m_colorSchemeSettings.value("AppsUseLightTheme").toBool() ? ColorScheme::Dark : ColorScheme::Light;
    #else //linux
    const 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
}

更新主题颜色和颜色方案

themeColorcolorScheme是两个可用于绑定的方法,它们返回当前的主题颜色和颜色方案,并在值发生变化时发出通知。这两个方法内部调用了私有成员函数的更新逻辑。

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_WIN
    return bool(pDwmSetWindowAttribute ? !pDwmSetWindowAttribute(HWND(window->winId()), 20, &isDark, sizeof(BOOL)) : false);
    #else
    return false;
    #endif //Q_OS_WIN
}

定时器事件处理

timerEvent方法是一个虚函数,用于处理定时器事件。它定期调用更新函数来检查主题颜色和颜色方案是否发生变化,并在变化时发出通知。

void SystemThemeHelper::timerEvent(QTimerEvent *)
{
    Q_D(SystemThemeHelper);
    d->_updateThemeColor();
    d->_updateColorScheme();
}

三、实现细节

SystemThemeHelperPrivateSystemThemeHelper的私有实现类,它封装了所有的实现细节和状态变量。这个类主要负责读取系统设置、更新主题颜色和颜色方案,并发出通知。

  • 构造函数与成员变量

    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.15

import DelegateUI.Utils 1.0

Window {
    id: window
    width: 640
    height: 480
    visible: true
    title: qsTr("SystemThemeHelper Test - ") + (themeHelper.colorScheme == SystemThemeHelper.Dark ? "Dark" : "Light")
    color: themeHelper.colorScheme == SystemThemeHelper.Dark ? "black" : "white"

    Behavior on color { ColorAnimation { } }

    SystemThemeHelper {
        id: themeHelper
        onThemeColorChanged: {
            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: parent
        text: qsTr("主题颜色")
        font.family: "微软雅黑"
        font.pointSize: 32
        color: themeHelper.themeColor
    }
}

【结语】

通过SystemThemeHelper类,我们可以在 Qt 应用程序中实现系统主题感知功能。

这个类封装了读取系统设置、更新主题颜色和颜色方案以及发出通知的逻辑,使得我们可以轻松地根据系统主题变化来调整应用程序的外观。

此外,通过条件编译和平台特定的实现,还确保了跨平台的兼容性。

以上就是基于Qt实现系统主题感知功能的详细内容,更多关于Qt系统主题感知的资料请关注脚本之家其它相关文章!

相关文章

  • C/C++中二进制文件&顺序读写详解及其作用介绍

    C/C++中二进制文件&顺序读写详解及其作用介绍

    这篇文章主要介绍了C/C++中二进制文件&顺序读写详解及其作用,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-09-09
  • C++示例讲解vector容器

    C++示例讲解vector容器

    这篇文章主要介绍了C++ 容器 Vector 的使用方法,Vector 是一个能够存放任意类型的动态数组,有点类似数组,是一个连续地址空间,下文更多详细内容的介绍,需要的小伙伴可以参考一下
    2022-07-07
  • C++中多线程的执行顺序如你预期吗

    C++中多线程的执行顺序如你预期吗

    这篇文章主要为大家详细介绍一下C++中多线程的执行顺序的相关资料,文中的示例代码讲解详细,对我们学习C++多线程有一定帮助,需要的可以参考一下
    2022-10-10
  • C++中运算符 &和&&、|和|| 的详解及区别

    C++中运算符 &和&&、|和|| 的详解及区别

    这篇文章主要介绍了C++中运算符 &和&&、|和|| 的详解及区别的相关资料,这里举例说明该如何区别他们的不同,需要的朋友可以参考下
    2016-11-11
  • Qt实现生成指定范围内随机数与随机字符串

    Qt实现生成指定范围内随机数与随机字符串

    这篇文章主要为大家详细介绍了如何利用Qt实现生成指定范围内随机数与随机字符串,文中的示例代码简洁易懂,感兴趣的小伙伴可以自己动手尝试一下
    2023-07-07
  • C++智能指针读书笔记

    C++智能指针读书笔记

    本篇随笔仅作为个人学习《C++ Primer》智能指针一节后的部分小结,抄书严重,伴随个人理解。主要介绍shared_ptr、make_shared、weak_ptr的用法和联系
    2015-11-11
  • C++中spdlog的简单使用示例

    C++中spdlog的简单使用示例

    spdlog是一个开源、跨平台、无依赖、只有头文件的C++11日志库,所以这篇文章主要来和大家介绍一下一个简单的spdlog使用示例,感兴趣的小伙伴可以了解一下
    2023-08-08
  • C语言实现选择题标准化考试系统

    C语言实现选择题标准化考试系统

    这篇文章主要为大家详细介绍了C语言实现选择题标准化考试系统,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-06-06
  • C语言实现停车管理系统

    C语言实现停车管理系统

    这篇文章主要为大家详细介绍了C语言实现停车管理系统,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-03-03
  • C++ 基于BFS算法的走迷宫自动寻路的实现

    C++ 基于BFS算法的走迷宫自动寻路的实现

    这篇文章主要为大家介绍了C++ 基于BFS算法实现走迷宫自动寻路,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-11-11

最新评论