Как переопределить только одну пару свойство: значение в Qt StyleSheet

Я пишу новичок в Qt5-коде для OSX Mavericks и хотел бы переопределить только одну пару свойство: значение таблицы стилей для данного виджета.

Если я запускаю следующий автономный демонстрационный код:

#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();
}

Я получаю приятную кнопку с настройками по умолчанию в стиле Macintosh - закругленные углы, стандартный OSX-синий цвет при нажатии и т.д.:

QPushButton с OSX по умолчанию

Однако, если я установил для таблицы стилей цвет фона кнопки красным, кажется, что в процессе я теряю все остальные настройки по умолчанию в стиле OSX - больше нет закругленных углов, стандартных полей и т. Д.:

#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();
}

Вот результат:

Переопределение стиля QPushButton с потерей других значений по умолчанию OSX

Как я могу переопределить только одно свойство: пара значений, сохраняя при этом остальные элементы стиля для виджета, например, в приведенном выше примере цвет фона будет красным, но все округления, поля и т. Д. Будут одинаковыми?

Большое спасибо

2 ответа

Решение

Ваш анализ в вашем комментарии о том, что вызов QApplication::setStyleSheet() полностью заменит активный в данный момент стиль, неверен. Вы правы, что текущий стиль заменен на QStyleSheetStyle, Тем не мение, QStyleSheetStyle делегирует его рисунок в оригинальный стиль, в вашем случае стиль Mac. Если вы посмотрите на источник QStyleSheetStyle, вы увидите это во многих местах, обращаясь к baseStyle()->drawControl(),

Это означает, что таблицы стилей работают с любым стилем. Теперь это явно не сработало в вашем случае, так что случилось? QStyleSheetStyle возвращается к рисованию в стиле Windows, если правила таблицы стилей не могут быть применены к базовому стилю. Это означает, что некоторые правила таблиц стилей работают хорошо, в то время как другие запускают запасной вариант. Ваши правила вызвали запасной вариант.

Я не думаю, что задокументировано, какие правила вызывают отступление. Для этого нам нужно взглянуть на источник, в этом случае QStyleSheetStyle:: drawControl (). Там мы найдем следующее:

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 это запасной стиль Windows. Ваше правило background-color марки rule.hasPalette() верните true, следовательно, вызывая запасной вариант.

Как освещено в параллельном посте Как получить всю Qt StyleSheet для QMacStyle, мой оригинальный вопрос был основан на запутанной предпосылке.

В Qt все виджеты оформляются с помощью QStyle (). По умолчанию для кода Qt в OSX (как в моем первом блоке демонстрационного кода в исходном вопросе), виджеты Qt стилизованы подклассом QStyle (), называемым QMacStyle () (фактически теперь, по-видимому, производным от QProxyStyle (), согласно страница QMacStyle - файл не найден).

Вызов функции setStyleSheet (), как и во втором блоке демонстрационного кода в исходном вопросе, создает экземпляр QStyleSheetStyle(), который затем полностью заменяет все, что QStyle ранее использовал для виджета - в этом случае красивый QMacStyle Я надеялся сохранить. Детали реализации этого можно увидеть, например, в qtbase/src/widgets/kernel/qapplication.cpp в QApplication::setStyleSheet() метод. Сам QStyleSheetStyle () находится в qtbase/src/widgets/styles/qstylesheetstyle.cpp, Как мелочи, QStyleSheetStyle () является производным от QWindowsStyle(), отсюда и появление окна в измененной кнопке в моем первоначальном вопросе.

Коротко говоря, Qt StyleSheets реализованы поверх QStyle (). Вызов setStyleSheet () неявно решает, что вы собираетесь использовать QStyleSheetStyle () вместо QMacStyle ().

Главная идея заключается в том, что при оформлении виджетов вам нужно выбрать подход, с компромиссами в любом случае. Вам нужно выбрать, какой QStyle () вы собираетесь использовать. Если вы запускаете код по умолчанию на Mac, вы решили начать с QMacStyle (). Затем вы можете изменить этот QStyle () в соответствии с существующей документацией. Если вы вызываете setStyleSheet (), вы неявно решили начать с QStyleSheetStyle(), который по умолчанию имеет вид QWindowsStyle (). Любые значения свойств таблицы стилей, которые вы затем примените, изменят этот внешний вид.

На мой вопрос, изложенный выше, есть два варианта. Одним из них является то, что человек может делать любые изменения внешнего вида полностью с помощью механизмов, доступных через QStyle (). Как это сделать, описано в другом месте. Другим вариантом будет создание с нуля таблицы стилей, которая воспроизводит внешний вид Mac для данного виджета, затем модифицирует его с помощью требуемых настроек и применяет его через setStyleSheet ().

В идеальном мире кто-то уже прошел бы это упражнение - то есть переварил qtbase/src/widgets/styles/qmacstyle_mac.mm в эквивалентную таблицу стилей - однако эта работа кажется обременительной, и не похоже, что кто-то сделал это, по крайней мере, с публичной публикацией. Я предполагаю, что другой отдаленно выполнимый вариант - переопределить QStyleSheetStyle, основанный на QMacStyle вместо QWindowsStyle, а затем каким-то образом интегрировать результат обратно в код (возможно, иметь setStyleSheet( QStyle* baseStyle, QString styleSheet)). Это, однако, далеко за пределами навыков новичка Qt, не говоря уже о текущей миссии.

Другие вопросы по тегам