基于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++ 动态数组的创建的实例详解的相关资料,希望通过本文能帮助到大家,让大家掌握这样的功能,需要的朋友可以参考下
    2017-10-10
  • C语言自定义类型超详细梳理之结构体 枚举 联合体

    C语言自定义类型超详细梳理之结构体 枚举 联合体

    今天我们来学习一下自定义类型,自定义类型包括结构体、枚举、联合体,小编觉得挺不错的,现在就分享给大家,也给大家做个参考
    2022-03-03
  • C++的optional用法实例详解

    C++的optional用法实例详解

    编程中我们可能会遇到要处理可能为空的变量,比如说容器,基本类型,或者说对象实例,下面通过实例代码介绍C++的optional用法,感兴趣的朋友一起看看吧
    2024-02-02
  • Qt使用QCamera实现切换相机,分辨率和图像捕获功能

    Qt使用QCamera实现切换相机,分辨率和图像捕获功能

    这篇文章主要为大家介绍了如何利用Qt中的相机类QCamera,取景器类QCameraViewfinder,图像捕获类QCameraImageCapture实现切换相机、分辨率和图像捕获功能,需要的可以了解一下
    2023-04-04
  • VSCode下.json文件的编写之(1) linux/g++ (2).json中参数与预定义变量的意义解释

    VSCode下.json文件的编写之(1) linux/g++ (2).json中参数与预定义变量的意义解释

    这篇文章主要介绍了VSCode下.json文件的编写之(1) linux/g++ (2).json中参数与预定义变量的意义解释,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-03-03
  • 详解OpenMP的线程同步机制

    详解OpenMP的线程同步机制

    在本篇文章当中主要给大家介绍 OpenMP 当中线程的同步和互斥机制,在 OpenMP 当中主要有三种不同的线程之间的互斥方式。下面就来和大家来讨论一下OpenMP当中的互斥操作,需要的可以参考一下
    2023-01-01
  • 利用C++的基本算法实现十个数排序

    利用C++的基本算法实现十个数排序

    以下是对利用C++的基本算法实现十个数排序的代码进行了介绍,需要的朋友可以过来参考下,希望对大家有所帮助
    2013-10-10
  • C语言:代码宏详解

    C语言:代码宏详解

    这篇文章主要介绍了 C语言宏定义使用实例详解的相关资料,需要的朋友可以参考下,希望能够给你带来帮助
    2021-09-09
  • 详解c语言实现的内存池(适用于两个线程、不加锁、效率高)

    详解c语言实现的内存池(适用于两个线程、不加锁、效率高)

    这篇文章主要介绍了c语言实现的内存池(适用于两个线程、不加锁、效率高),设计一个内存池,要求效率比系统调用的效率要高(测试1万次),同时支持一个线程申请,另外一个线程释放,需要的朋友可以参考下
    2024-02-02
  • C++线程安全的单例模式讲解

    C++线程安全的单例模式讲解

    今天小编就为大家分享一篇关于C++线程安全的单例模式讲解,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2019-01-01

最新评论