基于Qt實(shí)現(xiàn)系統(tǒng)主題感知功能
【正文開始】
一、使用效果
二、系統(tǒng)主題感知助手類(SystemThemeHelper)
SystemThemeHelper
類是一個(gè)封裝了系統(tǒng)主題感知功能的Qt對(duì)象。它主要通過讀取系統(tǒng)設(shè)置和監(jiān)聽系統(tǒng)主題變化來更新應(yīng)用程序的主題顏色和顏色方案。
類定義與屬性
在
systemthemehelper.h
中,SystemThemeHelper
類繼承自QObject
,并定義了兩個(gè)屬性:themeColor
和colorScheme
。這兩個(gè)屬性分別表示當(dāng)前的主題顏色和顏色方案(深色、淺色或無)。
class SystemThemeHelper : public QObject { Q_OBJECT Q_PROPERTY(QColor themeColor READ themeColor NOTIFY themeColorChanged) Q_PROPERTY(SystemThemeHelper::ColorScheme colorScheme READ colorScheme NOTIFY colorSchemeChanged) // ... };
ColorScheme
是一個(gè)枚舉類,定義了三種顏色方案:None
、Dark
和Light
。構(gòu)造函數(shù)與析構(gòu)函數(shù)
SystemThemeHelper
的構(gòu)造函數(shù)初始化了一些私有成員變量,并啟動(dòng)了一個(gè)定時(shí)器,用于定期更新主題顏色和顏色方案。析構(gòu)函數(shù)則負(fù)責(zé)清理資源。
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() { // 清理資源 }
獲取主題顏色和顏色方案
getThemeColor
和getColorScheme
是兩個(gè)不可用于綁定的方法,它們立即返回當(dāng)前的主題顏色和顏色方案,但不會(huì)觸發(fā)任何更新通知。這兩個(gè)方法主要用于快速獲取當(dāng)前設(shè)置,而不關(guān)心后續(xù)的變化。
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 }
更新主題顏色和顏色方案
themeColor
和colorScheme
是兩個(gè)可用于綁定的方法,它們返回當(dāng)前的主題顏色和顏色方案,并在值發(fā)生變化時(shí)發(fā)出通知。這兩個(gè)方法內(nèi)部調(diào)用了私有成員函數(shù)的更新邏輯。
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; }
設(shè)置窗口標(biāo)題欄模式
setWindowTitleBarMode
方法允許設(shè)置窗口標(biāo)題欄的模式(深色或淺色)。這個(gè)方法在Windows平臺(tái)上通過調(diào)用 DWM API
實(shí)現(xiàn),而在其他平臺(tái)上則不支持。
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 }
定時(shí)器事件處理
timerEvent
方法是一個(gè)虛函數(shù),用于處理定時(shí)器事件。它定期調(diào)用更新函數(shù)來檢查主題顏色和顏色方案是否發(fā)生變化,并在變化時(shí)發(fā)出通知。
void SystemThemeHelper::timerEvent(QTimerEvent *) { Q_D(SystemThemeHelper); d->_updateThemeColor(); d->_updateColorScheme(); }
三、實(shí)現(xiàn)細(xì)節(jié)
SystemThemeHelperPrivate
是SystemThemeHelper
的私有實(shí)現(xiàn)類,它封裝了所有的實(shí)現(xiàn)細(xì)節(jié)和狀態(tài)變量。這個(gè)類主要負(fù)責(zé)讀取系統(tǒng)設(shè)置、更新主題顏色和顏色方案,并發(fā)出通知。
構(gòu)造函數(shù)與成員變量
SystemThemeHelperPrivate
的構(gòu)造函數(shù)接收一個(gè)指向SystemThemeHelper
的指針,并初始化成員變量。成員變量包括主題顏色、顏色方案、定時(shí)器和一些平臺(tái)特定的設(shè)置對(duì)象。
SystemThemeHelperPrivate::SystemThemeHelperPrivate(SystemThemeHelper *q) : q_ptr(q) { // 初始化成員變量 }
更新函數(shù)
_updateThemeColor
和_updateColorScheme
是兩個(gè)更新函數(shù),它們檢查當(dāng)前的主題顏色和顏色方案是否發(fā)生變化,并在變化時(shí)更新成員變量并發(fā)出通知。
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(); } }
平臺(tái)特定的實(shí)現(xiàn)
在Windows平臺(tái)上,SystemThemeHelperPrivate
使用QSettings
來讀取系統(tǒng)主題設(shè)置,并使用DWM API來設(shè)置窗口標(biāo)題欄的模式。這些實(shí)現(xiàn)細(xì)節(jié)被封裝在條件編譯塊中,以確??缙脚_(tái)的兼容性。
#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函數(shù)指針 } #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 } }
【結(jié)語】
通過SystemThemeHelper
類,我們可以在 Qt 應(yīng)用程序中實(shí)現(xiàn)系統(tǒng)主題感知功能。
這個(gè)類封裝了讀取系統(tǒng)設(shè)置、更新主題顏色和顏色方案以及發(fā)出通知的邏輯,使得我們可以輕松地根據(jù)系統(tǒng)主題變化來調(diào)整應(yīng)用程序的外觀。
此外,通過條件編譯和平臺(tái)特定的實(shí)現(xiàn),還確保了跨平臺(tái)的兼容性。
以上就是基于Qt實(shí)現(xiàn)系統(tǒng)主題感知功能的詳細(xì)內(nèi)容,更多關(guān)于Qt系統(tǒng)主題感知的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
C/C++ 動(dòng)態(tài)數(shù)組的創(chuàng)建的實(shí)例詳解
這篇文章主要介紹了C/C++ 動(dòng)態(tài)數(shù)組的創(chuàng)建的實(shí)例詳解的相關(guān)資料,希望通過本文能幫助到大家,讓大家掌握這樣的功能,需要的朋友可以參考下2017-10-10C語言自定義類型超詳細(xì)梳理之結(jié)構(gòu)體 枚舉 聯(lián)合體
今天我們來學(xué)習(xí)一下自定義類型,自定義類型包括結(jié)構(gòu)體、枚舉、聯(lián)合體,小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考2022-03-03Qt使用QCamera實(shí)現(xiàn)切換相機(jī),分辨率和圖像捕獲功能
這篇文章主要為大家介紹了如何利用Qt中的相機(jī)類QCamera,取景器類QCameraViewfinder,圖像捕獲類QCameraImageCapture實(shí)現(xiàn)切換相機(jī)、分辨率和圖像捕獲功能,需要的可以了解一下2023-04-04VSCode下.json文件的編寫之(1) linux/g++ (2).json中參數(shù)與預(yù)定義變量的意義解釋
這篇文章主要介紹了VSCode下.json文件的編寫之(1) linux/g++ (2).json中參數(shù)與預(yù)定義變量的意義解釋,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-03-03利用C++的基本算法實(shí)現(xiàn)十個(gè)數(shù)排序
以下是對(duì)利用C++的基本算法實(shí)現(xiàn)十個(gè)數(shù)排序的代碼進(jìn)行了介紹,需要的朋友可以過來參考下,希望對(duì)大家有所幫助2013-10-10詳解c語言實(shí)現(xiàn)的內(nèi)存池(適用于兩個(gè)線程、不加鎖、效率高)
這篇文章主要介紹了c語言實(shí)現(xiàn)的內(nèi)存池(適用于兩個(gè)線程、不加鎖、效率高),設(shè)計(jì)一個(gè)內(nèi)存池,要求效率比系統(tǒng)調(diào)用的效率要高(測試1萬次),同時(shí)支持一個(gè)線程申請(qǐng),另外一個(gè)線程釋放,需要的朋友可以參考下2024-02-02