Qt QSS(二)之应用篇

Qt QSS(二)之应用篇

将QSS应用到Qt应用程序中

直接使用setStyleSheet("")来设置样式;

  1. 在一个应用程序性中设置背景颜色为黄色
    qApp->setStyleSheet("QLineEdit { background-color: yellow }");
  2. 如果需要设置指定对话框里的的 QLineEdits样式
    myDialog->setStyleSheet("QLineEdit { background-color: yellow }");
  3. 如果想使用在指定的 QLineEdit, 我们可以使用对象名QObject::setObjectName()和使用选择器ID:
    myDialog->setStyleSheet("QLineEdit#nameEdit { background-color: yellow }");
  4. 为文本设置合适颜色,用于形成明显的对比
    nameEdit->setStyleSheet("color: blue; background-color: yellow");
  5. 设置文本被选中时的颜色
nameEdit->setStyleSheet("color: blue;"
                        "background-color: yellow;"
                        "selection-color: yellow;"
                        "selection-background-color: blue;");

加载 QSS 文件的形式设置样式

  1. 新建QSS文件,后缀名为qss。例如:qstyle.qss
    为了方便使用,可以在Qt新建一个资源文件qstyle.qrc,用于存放样式文件。
    当然,也可以直接用绝对路径指向样式文件。

  2. 打开qstyle.qss,编写样式内容

QLineEdit { background-color: yellow }
  1. 加载QSS文件
    首先封装一个静态函数,用于实现样式的加载,方便在应用程序中使用。
#include 
#include 

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();
}
  1. 为了了解QApplication调用setStyleSheet()后,可以改变应用程序里的所有样式,我们需要进行源码的调试。QtCreator 设置了源码位置的,调试时可以进入到源码。
  • 首先我们进入到setStyleSheet(const QString& )查看其实现
void QApplication::setStyleSheet(const QString& styleSheet)
{
    //将样式内容保存到内存,以备候用
    QApplicationPrivate::styleSheet = styleSheet;
    //获取当前应用程序的样式
    QStyleSheetStyle *proxy = qobject_cast(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(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(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();
    }
}

你可能感兴趣的:(QSS,Qt)