zoukankan      html  css  js  c++  java
  • 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事件,达到全局样式更改。

  • 相关阅读:
    浅谈jQuery easyui datagrid操作单元格样式
    关于翻页之后表格重新加载,之前选中的项丢失的问题处理
    jquery操作复选框(checkbox)的12个小技巧总结
    项目管理学习笔记之四.风险管理
    c#基于udp实现的p2p语音聊天工具
    漫说好管理vs.坏管理
    linux安装tomcat
    wifi共享精灵2014.04.25.001已经更新,wifi热点中文名走起!
    NYOJ 589 糖果
    MacBook Pro安装Photoshop且支持Retina有你们说的那么困难吗!
  • 原文地址:https://www.cnblogs.com/whwywzhj/p/7604457.html
Copyright © 2011-2022 走看看