Qt之加載QSS文件


目錄(?)[+]

簡述

Qt中關於樣式的使用很常見,為了降低耦合性(與邏輯代碼分離),我們通常會定義一個QSS文件,然后編寫各種部件(例如:QLable、QLineEdit、QPushButton)的樣式,最后使用QApplication進行樣式加載,這樣,就可以讓整個應用程序就共享同一個樣式。

 

 

新建QSS文件

首先,新建一個后綴名為qss的文件,例如:style.qss,將其加入資源文件(qrc)中。

提示:也可以使用絕對路徑或相對路徑。

編寫QSS

在style.qss文件中編寫自己的樣式代碼,例如:

QToolTip { border: 1px solid rgb(45, 45, 45); background: white; color: black; }

加載QSS

為了方便以后調用,可以寫一個靜態加載樣式的函數:

#include <QFile> #include <QApplication>  class CommonHelper { public: static void setStyle(const QString &style) { QFile qss(style); qss.open(QFile::ReadOnly); qApp->setStyleSheet(qss.readAll()); qss.close(); } };

 

然后,在主函數里進行加載:

int main(int argc, char *argv[]) { QApplication a(argc, argv); // 加載QSS樣式 CommonHelper::setStyle("style.qss"); MainWindow window; window.show(); return a.exec(); }

實現原理

很容易發現,原來qApp是QCoreApplication的一個單例,然后,將其轉換為QApplication。

#if defined(qApp) #undef qApp #endif #define qApp (static_cast<QApplication *>(QCoreApplication::instance()))
  • 1
  • 2
  • 3
  • 4

那么,QApplication調用setStyleSheet()以后為何所有的部件樣式都改變了呢?

通過逐層分析,我們發現其主要是調用了setStyle():

void QApplication::setStyle(QStyle *style) { if (!style || style == QApplicationPrivate::app_style) return; QWidgetList all = allWidgets(); // clean up the old style if (QApplicationPrivate::app_style) { if (QApplicationPrivate::is_app_running && !QApplicationPrivate::is_app_closing) { for (QWidgetList::ConstIterator it = all.constBegin(), cend = all.constEnd(); it != cend; ++it) { QWidget *w = *it; if (!(w->windowType() == Qt::Desktop) && // except desktop w->testAttribute(Qt::WA_WState_Polished)) { // has been polished QApplicationPrivate::app_style->unpolish(w); } } } QApplicationPrivate::app_style->unpolish(qApp); } QStyle *old = QApplicationPrivate::app_style; // save QApplicationPrivate::overrides_native_style = nativeStyleClassName() == QByteArray(style->metaObject()->className()); #ifndef QT_NO_STYLE_STYLESHEET if (!QApplicationPrivate::styleSheet.isEmpty() && !qobject_cast<QStyleSheetStyle *>(style)) { // we have a stylesheet already and a new style is being set QStyleSheetStyle *newProxy = new QStyleSheetStyle(style); style->setParent(newProxy); QApplicationPrivate::app_style = newProxy; } else #endif // QT_NO_STYLE_STYLESHEET QApplicationPrivate::app_style = style; QApplicationPrivate::app_style->setParent(qApp); // take ownership // take care of possible palette requirements of certain gui // styles. Do it before polishing the application since the style // might call QApplication::setPalette() itself if (QApplicationPrivate::set_pal) { QApplication::setPalette(*QApplicationPrivate::set_pal); } else if (QApplicationPrivate::sys_pal) { clearSystemPalette(); initSystemPalette(); QApplicationPrivate::initializeWidgetPaletteHash(); QApplicationPrivate::initializeWidgetFontHash(); QApplicationPrivate::setPalette_helper(*QApplicationPrivate::sys_pal, /*className=*/0, /*clearWidgetPaletteHash=*/false); } else if (!QApplicationPrivate::sys_pal) { // Initialize the sys_pal if it hasn't happened yet... QApplicationPrivate::setSystemPalette(QApplicationPrivate::app_style->standardPalette()); } // initialize the application with the new style QApplicationPrivate::app_style->polish(qApp); // re-polish existing widgets if necessary if (QApplicationPrivate::is_app_running && !QApplicationPrivate::is_app_closing) { for (QWidgetList::ConstIterator it = all.constBegin(), cend = all.constEnd(); it != cend; ++it) { QWidget *w = *it; if (w->windowType() != Qt::Desktop && w->testAttribute(Qt::WA_WState_Polished)) { if (w->style() == QApplicationPrivate::app_style) QApplicationPrivate::app_style->polish(w); // repolish #ifndef QT_NO_STYLE_STYLESHEET else w->setStyleSheet(w->styleSheet()); // touch #endif } } for (QWidgetList::ConstIterator it = all.constBegin(), cend = all.constEnd(); it != cend; ++it) { QWidget *w = *it; if (w->windowType() != Qt::Desktop && !w->testAttribute(Qt::WA_SetStyle)) { QEvent e(QEvent::StyleChange); QApplication::sendEvent(w, &e); w->update(); } } } #ifndef QT_NO_STYLE_STYLESHEET if (QStyleSheetStyle *oldProxy = qobject_cast<QStyleSheetStyle *>(old)) { oldProxy->deref(); } else #endif if (old && old->parent() == qApp) { delete old; } if (QApplicationPrivate::focus_widget) { QFocusEvent in(QEvent::FocusIn, Qt::OtherFocusReason); QApplication::sendEvent(QApplicationPrivate::focus_widget->style(), &in); QApplicationPrivate::focus_widget->update(); } }

 

主要分為4步:

  1. 清理舊樣式 - unpolish()
  2. 初始化新樣式 - polish()
  3. 加載新樣式 - polish() + sendEvent()、update()
  4. 刪除舊樣式 - delete

通過調用QWidgetList all = allWidgets()獲取了所有控件的集合,然后,利用迭代器QWidgetList::ConstIterator對每一個控件進行處理,最后,通過QApplication::sendEvent()來發送QEvent::StyleChange事件,達到全局樣式更改。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM