Поясните про стили в Qt [QSS, QStyle]
От: nen777w  
Дата: 14.01.14 19:35
Оценка: 1 (1)
Есть Qt widget-based приложение, хочется сделать красивый UI.
Порылся в интернете нашел файл со стилями которую хочу взять за основу.

Но столкнулся вот с такой проблемой:
Так как виджетов в приложении создается много, то наблюдается такая штука, если применять стили, например так:

app.exe -stylesheet=darkorange.stylesheet

то приложение начинает оочень долго запускаться.
Если я правильно понимаю что происходит, то происходит компиляция стиля для каждого виджета отдельно, отсюда и тормоза.

Вопрос, можно ли как это это ускорить?
Например написанием своего наследника QStyle, подумал так потому что например есть станадртные стили которые можно выставить например так:
QApplication::setStyle(QStyleFactory::create("plastique"));


Вообще очень интересно эти две штуки QSS и QStyle они взаимозаменяемы, или дополняют друг друга?
Re: Поясните про стили в Qt [QSS, QStyle]
От: _niko_ Россия  
Дата: 14.01.14 20:33
Оценка: 17 (3)
Здравствуйте, nen777w, Вы писали:

N>Вообще очень интересно эти две штуки QSS и QStyle они взаимозаменяемы, или дополняют друг друга?

В основе стилей всегда лежит класс QStyle, даже если стиль описан с помощью QSS (QStyleSheetStyle). В свою очередь любой объект стиля можно проксировать (QProxyStyle).
Следовательно они дополняют друг друга, но тут есть одно "НО": реализация QStyleSheetStyle не идеальна для "скрещивания" с другими объектами стилей — не всегда получается ожидаемое
Да и когда все виджеты в приложении отрисовываются через QSS отрисовка заметно приседает, очень показателен resize'инг окна.

N>Если я правильно понимаю что происходит, то происходит компиляция стиля для каждого виджета отдельно, отсюда и тормоза.

Объект стиля установленный приложению устанавливается всем виджетам этого приложения — никакой дополнительной "компиляции" не происходит.
Тут дело может быть в следующем методе:
static void updateWidgets(const QList<const QWidget *>& widgets)
{
    if (!styleSheetCaches->styleRulesCache.isEmpty() || !styleSheetCaches->hasStyleRuleCache.isEmpty() || !styleSheetCaches->renderRulesCache.isEmpty()) {
        for (int i = 0; i < widgets.size(); ++i) {
            const QWidget *widget = widgets.at(i);
            styleSheetCaches->styleRulesCache.remove(widget);
            styleSheetCaches->hasStyleRuleCache.remove(widget);
            styleSheetCaches->renderRulesCache.remove(widget);
        }
    }
    for (int i = 0; i < widgets.size(); ++i) {
        QWidget *widget = const_cast<QWidget *>(widgets.at(i));
        if (widget == 0)
            continue;
        widget->style()->polish(widget);
        QEvent event(QEvent::StyleChange);
        QApplication::sendEvent(widget, &event);
        widget->update();
        widget->updateGeometry();
    }
}


Который вызывается для каждого виджета "знакомящегося" со стилем:
void QStyleSheetStyle::repolish(QApplication *app)
{
    Q_UNUSED(app);
    const QList<const QWidget*> allWidgets = styleSheetCaches->styleRulesCache.keys();
    styleSheetCaches->styleSheetCache.remove(qApp);
    styleSheetCaches->styleRulesCache.clear();
    styleSheetCaches->hasStyleRuleCache.clear();
    styleSheetCaches->renderRulesCache.clear();
    updateWidgets(allWidgets);
}
void QStyleSheetStyle::repolish(QWidget *w)
{
    QList<const QWidget *> children = w->findChildren<const QWidget *>(QString());
    children.append(w);
    styleSheetCaches->styleSheetCache.remove(w);
    updateWidgets(children);
}


N>Вопрос, можно ли как это это ускорить?

Написание собственного класса стиля будет идеальным решением, тем более что нет необходимости реализовывать все с нуля:
наследуемся от какого либо класса из стандартных стилей и корректируем отображение нужных элементов под себя — благо все методы виртуальны и исходники (как образец) всегда под рукой
Re[2]: Поясните про стили в Qt [QSS, QStyle]
От: nen777w  
Дата: 14.01.14 22:22
Оценка:
N>>Вопрос, можно ли как это это ускорить?
__>Написание собственного класса стиля будет идеальным решением, тем более что нет необходимости реализовывать все с нуля:
__>наследуемся от какого либо класса из стандартных стилей и корректируем отображение нужных элементов под себя — благо все методы виртуальны и исходники (как образец) всегда под рукой

Спасибо за развернутый ответ. Т.е. если я понял правильно нужно унаследоваться от QProxyStyle и вперёд писать свой стиль.
Не скромный вопрос... а есть ли где то что то уже готовое? Я нашел пример в доке, и вроде бы ничего такого сложного, но всё же взять что то готовое и допилить до своих нужд, проще чем писать все с 0-я.
Re: Поясните про стили в Qt [QSS, QStyle]
От: ichan  
Дата: 14.01.14 23:20
Оценка: 5 (1)
Здравствуйте, nen777w, Вы писали:

N>Есть Qt widget-based приложение, хочется сделать красивый UI.


N>то приложение начинает оочень долго запускаться.

N>Если я правильно понимаю что происходит, то происходит компиляция стиля для каждого виджета отдельно, отсюда и тормоза.


N>QApplication::setStyle(QStyleFactory::create("plastique"));

N>[/ccode]

N>Вообще очень интересно эти две штуки QSS и QStyle они взаимозаменяемы, или дополняют друг друга?


Посмотри [url=http://stackoverflow.com/questions/18187376/stylesheet-performance-hits-with-qt]
еще можно попробовать задавать для для каждого widge-та минимальный стиль который относиться только к нему.
В ui файле есть свойство stylesheet.
Re[2]: Поясните про стили в Qt [QSS, QStyle]
От: _niko_ Россия  
Дата: 15.01.14 07:22
Оценка:
Здравствуйте, ichan, Вы писали:

I>Посмотри [url=http://stackoverflow.com/questions/18187376/stylesheet-performance-hits-with-qt]

I>еще можно попробовать задавать для для каждого widge-та минимальный стиль который относиться только к нему.
I>В ui файле есть свойство stylesheet.

Тут хотелось бы отметить что:
— установив stylesheet родительскому виджету этот стиль так же используется и в дочернем как база;
— задавая стиль виджету через QSS (свойство stylesheet) создается новый объект стиля QStyleSheetStyle который проксирует стиль уже имеющийся у виджета.

Таким макаром как мне представляется можно нагородить кучу не быстрых объектов класса QStyleSheetStyle которые будут так или иначе использоваться при отрисовки одного виджета (хотя тут я не уверен на все 100).
Re[3]: Поясните про стили в Qt [QSS, QStyle]
От: _niko_ Россия  
Дата: 15.01.14 07:22
Оценка:
Здравствуйте, nen777w, Вы писали:

N>Спасибо за развернутый ответ. Т.е. если я понял правильно нужно унаследоваться от QProxyStyle и вперёд писать свой стиль.

Если ограничиться какими то простыми вещами — да, проксирование это то что нада.
Если речь идет о собственном представлении комбинированного контрола то тут уже может быть придется писать свой стиль.

N>Не скромный вопрос... а есть ли где то что то уже готовое? Я нашел пример в доке, и вроде бы ничего такого сложного, но всё же взять что то готовое и допилить до своих нужд, проще чем писать все с 0-я.

Если найдете готовые решения стилей буду рад ссылке (думается мне что такие вещи в нете не валяются)

В проксировании ещё кроется один подвох:
— стиль с которым связали проксирующий "знает" об этом;
— знать стить может только об одном проксирующем стиле.

Установив стиль приложению он будет использоваться для всех виджетов.
Следовательно: установив один проксирующий стиль скажем для QLineEdit, а другой проксирующий стиль для QComboBox (с поддержкой ввода) — отображение QLineEdit будет другим.
Re: Поясните про стили в Qt [QSS, QStyle]
От: SaZ  
Дата: 15.01.14 09:27
Оценка:
Здравствуйте, nen777w, Вы писали:

N>...

N>Вообще очень интересно эти две штуки QSS и QStyle они взаимозаменяемы, или дополняют друг друга?

Тут много интересного уже написали. Я в догонку кину ссылочку: http://habrahabr.ru/post/149687/
Re[2]: Поясните про стили в Qt [QSS, QStyle]
От: SaZ  
Дата: 15.01.14 09:34
Оценка:
И ещё, QSS (да и сами виджеты) в плане кастомизации — вещь очень ограниченная в плане анимации интерфейсов. В лучшем случае у вас будет несколько состояний (normal/hover/pressed и т.п.) — и для них свои стили, между которыми и будет проходить переключение. А вот задать анимацию переключения через QSS не получится (как, например, "плавно" подсвечивается стандартная виндовая кнопка при наведении мыши).
Я как-то пробовал добиться похожего поведения через комбинирование QSS и QProxyStyle, но это получалось жуткое костылестроение. А реализовывать свою полноценную систему стилей (переопределяя QStyle) с реализацией анимации — достаточно сложно.
Re[3]: Поясните про стили в Qt [QSS, QStyle]
От: nen777w  
Дата: 15.01.14 09:51
Оценка:
SaZ>И ещё, QSS (да и сами виджеты) в плане кастомизации — вещь очень ограниченная в плане анимации интерфейсов. В лучшем случае у вас будет несколько состояний (normal/hover/pressed и т.п.) — и для них свои стили, между которыми и будет проходить переключение. А вот задать анимацию переключения через QSS не получится (как, например, "плавно" подсвечивается стандартная виндовая кнопка при наведении мыши).
SaZ>Я как-то пробовал добиться похожего поведения через комбинирование QSS и QProxyStyle, но это получалось жуткое костылестроение. А реализовывать свою полноценную систему стилей (переопределяя QStyle) с реализацией анимации — достаточно сложно.

Да мне я думаю не нужно анимаций.
Хочется добиться что бы приложение выглядело как Photoshop.
Помоему и UI некоторых продуктов Adobe на Qt сделан?
Re[4]: Поясните про стили в Qt [QSS, QStyle]
От: SaZ  
Дата: 15.01.14 11:36
Оценка: 10 (1)
Здравствуйте, nen777w, Вы писали:

N>Да мне я думаю не нужно анимаций.

N>Хочется добиться что бы приложение выглядело как Photoshop.
N>Помоему и UI некоторых продуктов Adobe на Qt сделан?

Я когда-то писал вот эту прогу. Там кастомизации через QSS ну очень много. Программа маленкая, но было замечено следующее:
— Любые градиентные фоны долго рисуются. Особенно при изменении размеров окна.
— Возможности кастомизации tab контрола очень ограниченные.
— Периодические проблемы с подгонкой размеров контролов. Лэйауты вели себя далеко не всегда так, как задумано.
— Достаточно сложно оказалось побороть баг в Qt.
— Иерархию стилей / структуру именования контролов нужно сразу продумывать очень тщательно. Возможно, не стоит пихать все стили в один файл.
— QStyle::drawControl работает далеко не всегда.
— QGroupBox кастомизируется очень неадекватно. Нужно много плясать с margin/padding.

Небольшие хинты, которые мне помогли:
— Если стиль завязан на какой-либо property, то чтобы контрол конкретно обновлял свои стили, то нужно дёргать polish()+unpolish().
— Если виджет лежит в неймспейте, то в qss в имени класса вместо :: нужно использовать --.
— Вообще тут много интересного.
— Фоновые картинки (для всего контрола) порой проще задавать через border-image.
— Для кнопок, если нужно менять отображение текста при hover событиях (например, сделать hyperlink) нужно использовать QToolButton вместо QPushButton.

Отпишусь ещё, если вспомню чего интересного.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.