QT全局所有QSS样式实时切换
方法如下:
void loadQss(int qssType)
{
QString name;
if (qssType == 1)
name = ":/qss/day.qss";
else
name = ":/qss/night.qss";
QFile file(name);
file.open(QFile::ReadOnly);
QString qss;
qss = file.readAll();
qApp->setStyleSheet(qss);
file.close();
}
为什么qApp->setStyleSheet(qss);可以做到全局所有样式实时切换,我来看下setStyleSheet的源码。
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);
}
}
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();
}
}
通过以上源码我们能看出在qApp的setStyleSheet中会拿到所有控件,清除旧的样式,然后加载新的样式,做到全局所有控件样式的动态切换。