Qt QSS(二)之應用篇
將QSS應用到Qt應用程序中
直接使用setStyleSheet("")
來設置樣式;
- 在一個應用程序性中設置背景顏色爲黃色
qApp->setStyleSheet("QLineEdit { background-color: yellow }");
- 如果需要設置指定對話框裏的的
QLineEdits
樣式
myDialog->setStyleSheet("QLineEdit { background-color: yellow }");
- 如果想使用在指定的
QLineEdit
, 我們可以使用對象名QObject::setObjectName()
和使用選擇器ID:
myDialog->setStyleSheet("QLineEdit#nameEdit { background-color: yellow }");
- 爲文本設置合適顏色,用於形成明顯的對比
nameEdit->setStyleSheet("color: blue; background-color: yellow");
- 設置文本被選中時的顏色
nameEdit->setStyleSheet("color: blue;"
"background-color: yellow;"
"selection-color: yellow;"
"selection-background-color: blue;");
加載 QSS 文件的形式設置樣式
-
新建QSS文件,後綴名爲qss。例如:
qstyle.qss
爲了方便使用,可以在Qt新建一個資源文件qstyle.qrc,用於存放樣式文件。
當然,也可以直接用絕對路徑指向樣式文件。 -
打開
qstyle.qss
,編寫樣式內容
QLineEdit { background-color: yellow }
- 加載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();
}
- 爲了瞭解QApplication調用setStyleSheet()後,可以改變應用程序裏的所有樣式,我們需要進行源碼的調試。QtCreator 設置了源碼位置的,調試時可以進入到源碼。
- 首先我們進入到setStyleSheet(const QString& )查看其實現
void QApplication::setStyleSheet(const QString& styleSheet)
{
//將樣式內容保存到內存,以備候用
QApplicationPrivate::styleSheet = styleSheet;
//獲取當前應用程序的樣式
QStyleSheetStyle *proxy = qobject_cast<QStyleSheetStyle*>(QApplicationPrivate::app_style);
//第一個判斷條件:如果傳入樣式爲空,則保持當前應該用程序樣式
if (styleSheet.isEmpty()) { // application style sheet removed
if (!proxy)
return; // there was no stylesheet before
setStyle(proxy->base);
//如果應用程序已經設置了樣式,則只是刷新樣式,而不會使用函數傳入的樣式。
//這也就告訴我們,爲qApp設置樣式前,需要卸載當前樣式,之後安裝樣式才能生效
} else if (proxy) { // style sheet update, just repolish
proxy->repolish(qApp);
//當前qApp沒有樣式,設置我們傳進來的樣式
} else { // stylesheet set the first time
QStyleSheetStyle *newProxy = new QStyleSheetStyle(QApplicationPrivate::app_style);
QApplicationPrivate::app_style->setParent(newProxy);
setStyle(newProxy);
}
}
上面的中文註釋,解釋了這段代碼的運行機制。我們最終設置樣式是通過setStyle(QStyle *style)這個函數實現的。 源碼如下:
從上到下解釋運行邏輯。
- 傳入樣式必須有效,且樣式必須是新樣式
- QWidgetList all = allWidgets(); 獲取應用程序所有控件
- 清除所有老樣式
unpolish(QWidget*)
- 樣式有效, 關聯新樣式QApplicationPrivate::app_style->setParent(qApp);
- 初始化樣式 polish()
- 將新樣式應用到所有子控件中 polish() + sendEvent()、update()
- 刪除舊樣式 - delete
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();
}
}