Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
483 views
in Technique[技术] by (71.8m points)

qt5 - How to override just one property:value pair in Qt StyleSheet

I am writing newbie Qt5 code on OSX Mavericks and would like to override just one property:value pair of the StyleSheet for a given widget.

If I run the following self-contained demonstration code:

#include <QApplication>
#include <QMainWindow>
#include <QtGui>
#include <QPushButton>

int
main( int argc, char *argv[] ) {
    QApplication app( argc, argv );

    QMainWindow* mw = new QMainWindow();

    QPushButton* AButton = new QPushButton( "A Button", mw );

    mw->show();

    return app.exec();
}

I get a nice pushbutton with Macintosh style defaults -- rounded corners, standard OSX-blue color when pressed, etc.:

QPushButton with OSX defaults

If however I set the stylesheet to make the background button color red, it seems I lose all the other OSX style defaults in the process -- no more rounded corners, standard margins, etc.:

#include <QApplication>
#include <QMainWindow>
#include <QtGui>
#include <QPushButton>

int
main( int argc, char *argv[] ) {
    QApplication app( argc, argv );

    QMainWindow* mw = new QMainWindow();

    QPushButton* AButton = new QPushButton( "A Button", mw );

    AButton->setStyleSheet("QPushButton { background-color: red; }");

    mw->show();

    return app.exec();
}

Here's the result:

QPushButton style override, with loss of other OSX defaults

How can I override just one property:value pair while preserving the rest of the style elements for the widget, e.g. in the example above make the background color red but keep all the border rounding, margins etc. the same?

Thanks much

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Your analysis in your comment that a call to QApplication::setStyleSheet() will completely replace the currently active style is incorrect. You are right that a the current style is replaced with QStyleSheetStyle. However, QStyleSheetStyle delegates its drawing to the original style, in your case the Mac style. If you look at the source of QStyleSheetStyle, you'll see this in many places, calls to baseStyle()->drawControl().

This means stylesheets work on any style. Now, it clearly didn't work in your case, so what happened? QStyleSheetStyle falls back to drawing in the Windows style if the style sheet rules can't be applied to the base style. That means that some style sheet rules work nicely, while others will trigger the fallback. Your rules triggered the fallback.

I don't think it's documented which rules trigger the fallback. For that we need to look at the source, in this case QStyleSheetStyle::drawControl(). We'll find the following in there:

case CE_PushButton:
    if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(opt)) {
        if (rule.hasDrawable() || rule.hasBox() || rule.hasPosition() || rule.hasPalette() ||
                ((btn->features & QStyleOptionButton::HasMenu) && hasStyleRule(w, PseudoElement_PushButtonMenuIndicator))) {
            ParentStyle::drawControl(ce, opt, p, w);
            return;
        }
    }

ParentSyle is the fallback Windows style. Your rule background-color makes rule.hasPalette() return true, therefore triggering the fallback.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...