Style Sheet и Dynamic Properties
От: XOOIOOX  
Дата: 28.12.16 21:30
Оценка:
Есть такая довольно удобная вещь, как Dynamic Properties. Т.е., например, в родительском виджете задаем Style Sheet:

QPushButton[style="1"] { background-color: rgb(0, 255, 0); }
QPushButton[style="2"] { background-color: rgb(255, 0, 0); }


Далее меняем эту динамическую пропертию у виджетов, скажем, как-то так:

void SetWidgetProperty(QWidget* obj, const char *name, const int prop)
{
    obj->setProperty(name, prop);
    obj->style()->unpolish(obj);
    obj->style()->polish(obj);
}


Все пушбутоны меняют цвет в зависимости от выставленной пропертии.

Вопрос в том, можно ли обойтись без такой шизоидной темы, как обработка этим методом каждого из 100500 виджетов на форме? Хотя все виджеты на форме наследуются, изменение динамической пропертии у родительского виджета не наследуется, не раздупляются дочерние виджеты. Есть варианты выкрутиться?
Re: Style Sheet и Dynamic Properties
От: Igore Россия  
Дата: 29.12.16 11:03
Оценка: -1
Здравствуйте, XOOIOOX, Вы писали:

XOO>Все пушбутоны меняют цвет в зависимости от выставленной пропертии.

XOO>Вопрос в том, можно ли обойтись без такой шизоидной темы, как обработка этим методом каждого из 100500 виджетов на форме? Хотя все виджеты на форме наследуются, изменение динамической пропертии у родительского виджета не наследуется, не раздупляются дочерние виджеты. Есть варианты выкрутиться?
setStyleSheet( styleSheet() );
Re[2]: Style Sheet и Dynamic Properties
От: XOOIOOX  
Дата: 29.12.16 12:41
Оценка:
Здравствуйте, Igore, Вы писали:

I>setStyleSheet( styleSheet() );


Не, не работает.

Например, такой тестовый код:

#include <QtCore>
#include "ui_test0074.h"

class TEST0074 : public QDialog
{
    Q_OBJECT

public:
    TEST0074(QWidget *parent = 0);
    ~TEST0074();

private:
    Ui::Okno ui;
    void setProp(QWidget* obj, const char *name, const int prop);

    public slots:
    void state1();
    void state2();
    void state3();
};


#include "TEST0074.h"

TEST0074::TEST0074(QWidget *parent) : QDialog(parent)
{
    ui.setupUi(this);
    connect(ui.pushButton, SIGNAL(clicked()), this, SLOT(state1()), Qt::QueuedConnection);
    connect(ui.pushButton_2, SIGNAL(clicked()), this, SLOT(state2()), Qt::QueuedConnection);
    connect(ui.pushButton_3, SIGNAL(clicked()), this, SLOT(state3()), Qt::QueuedConnection);
}

TEST0074::~TEST0074(){}

void TEST0074::setProp(QWidget* obj, const char *name, const int prop)
{
    obj->setProperty(name, prop);
    obj->setStyleSheet(obj->styleSheet());
    obj->style()->unpolish(obj);
    obj->style()->polish(obj);
}

void TEST0074::state1()
{
    setProp(ui.widget, "urgent", 1);
}

void TEST0074::state2()
{
    setProp(ui.widget, "urgent", 2);
}

void TEST0074::state3()
{
    setProp(ui.widget, "urgent", 0);
}


На форме три бутона, которые которые наследуются от ui.widget.

Стайлшит на родительском виджете такой:

QPushButton{background-color: rgb(0, 0, 255);}
QPushButton[urgent="1"]{background-color: rgb(0, 255, 0);}
QPushButton[urgent="2"]{background-color: rgb(255, 0, 0);}


Работает только в случае, как уже говорил выше, если каждый бутон обрабатывать отдельно.
Re[3]: Style Sheet и Dynamic Properties
От: Igore Россия  
Дата: 29.12.16 13:54
Оценка:
Здравствуйте, XOOIOOX, Вы писали:

XOO>Не, не работает.

XOO>Работает только в случае, как уже говорил выше, если каждый бутон обрабатывать отдельно.
Не, я предложил у главной формы обновить стиль, this->setStyleSheet( this->styleSheet() ), не надо поотдельности каждую кнопку мучить, потом вроде надо update вызвать и все.
Re[4]: Style Sheet и Dynamic Properties
От: XOOIOOX  
Дата: 29.12.16 15:19
Оценка:
Здравствуйте, Igore, Вы писали:

I>Не, я предложил у главной формы обновить стиль, this->setStyleSheet( this->styleSheet() )


Это я все пробовал. Не взлетает.
Re[2]: Style Sheet и Dynamic Properties
От: SaZ  
Дата: 30.12.16 01:06
Оценка:
Здравствуйте, Igore, Вы писали:

I>setStyleSheet( styleSheet() );


Это в целом тоже самое (по результату), что polish/unpolish, только qss заново парсится. Со всеми вытекающими просадками производительности. На сильно кастомизированных интерфейсах у меня дико тормозило.
Re: Style Sheet и Dynamic Properties
От: SaZ  
Дата: 30.12.16 01:08
Оценка:
Здравствуйте, XOOIOOX, Вы писали:


XOO>...

XOO>
XOO>void SetWidgetProperty(QWidget* obj, const char *name, const int prop)
XOO>{
    obj->>setProperty(name, prop);
    obj->>style()->unpolish(obj);
    obj->>style()->polish(obj);
XOO>}
XOO>

XOO>...
XOO>Вопрос в том, можно ли обойтись без такой шизоидной темы, как обработка этим методом каждого из 100500 виджетов на форме? Хотя все виджеты на форме наследуются, изменение динамической пропертии у родительского виджета не наследуется, не раздупляются дочерние виджеты. Есть варианты выкрутиться?

Если я правильно понял, то стоит копнуть в сторону обработки QDynamicPropertyChangeEvent
Re[2]: Style Sheet и Dynamic Properties
От: XOOIOOX  
Дата: 30.12.16 01:40
Оценка:
Здравствуйте, SaZ, Вы писали:

SaZ>Если я правильно понял, то стоит копнуть в сторону обработки QDynamicPropertyChangeEvent


Дык ивент же не будет рождаться, если пропертия у каждого виджета не изменилась. А она, насколько понимаю, не меняется, не наследуется от родительского. От родительского ивент-то придет при смене, но объектом по ивент-фильтру будет родительский класс и все.

Так же пробовал явно указывать на форме эту пропертию везде, пробовал основному родительскому классу ее задавать до setupUi — толку ноль.

Может она по-умолчанию и не должна наследоваться (что довольно печально), но можно где-то какой-то атрибут крутануть у QCoreApplication?
Re[3]: Style Sheet и Dynamic Properties
От: SaZ  
Дата: 01.01.17 10:02
Оценка:
Здравствуйте, XOOIOOX, Вы писали:

XOO>Дык ивент же не будет рождаться, если пропертия у каждого виджета не изменилась. А она, насколько понимаю, не меняется, не наследуется от родительского. От родительского ивент-то придет при смене, но объектом по ивент-фильтру будет родительский класс и все.


Ммм. Зачем вы виджеты рассматриваете группой? Цепляйте эвент фильтр на каждый виджет, который нужно отслеживать.

XOO>Так же пробовал явно указывать на форме эту пропертию везде, пробовал основному родительскому классу ее задавать до setupUi — толку ноль.


До setupUi смысла нет. Виджеты же именно там конструируются.

XOO>Может она по-умолчанию и не должна наследоваться (что довольно печально), но можно где-то какой-то атрибут крутануть у QCoreApplication?


Как проперти могут наслезоваться? Это невиртуальная функциональность класса QObject.
Re[4]: Style Sheet и Dynamic Properties
От: XOOIOOX  
Дата: 01.01.17 15:00
Оценка:
Здравствуйте, SaZ, Вы писали:

SaZ>Цепляйте эвент фильтр на каждый виджет, который нужно отслеживать.


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

И опять же, допустим, я буду генерить свой особый кастомный общий ивент на все, который будет обходить весь ивент-луп и контролить его присутствие во всех виджетах — где заканчивать его обработку? Дойдет ли он до всех виджетов?

SaZ>До setupUi смысла нет.


Да по-всякому пробовал и до и после.

SaZ>Как проперти могут наслезоваться?


Имеется в виду "наследование" изменения этой пропертии хотя бы. Саму пропертию можно задать на форме, она останется у объектов, а вот ее изменение приходится делать у каждого объекта, как теперь понимаю, без вариантов.
Re[5]: Style Sheet и Dynamic Properties
От: SaZ  
Дата: 02.01.17 12:01
Оценка: 2 (1) +1
Здравствуйте, XOOIOOX, Вы писали:

XOO>Имхо, получается шило на мыло и даже хуже по объему дополнительного кода. В изначальной реализации я прописываю максимум одну строку с виджетом в метод, а в этом случае нужно ивент-фильтр на каждый тип виджета вешать.


Циклы в помощь. Я думаю не стоит особо заморачиваться между 1-й строкой кода и тремя.

auto buttons = rootWidget->findChildren<QPushButton *>();
for ( const auto& button : buttons )
  button->installEventFilter( myFilter );


XOO>И опять же, допустим, я буду генерить свой особый кастомный общий ивент на все, который будет обходить весь ивент-луп и контролить его присутствие во всех виджетах — где заканчивать его обработку? Дойдет ли он до всех виджетов?


У вас в обработчике эвента будет и QObject *, который можно qobject_cast<QPushButton *>( obj );. Ничего заканчивать не нужно. Но если уж хочется красиво, то можно такой вот паттерн заюзать, чтобы дёргать обновление не сильно часто:

QTimer t;
t.setSingleShot( true );
t.setTimeout( 0 ); // Возможно, надо чуть больше нуля
connect( &t, &QTimer::timeout, widget, [&](){ widget->polish(); widget->unpolish(); } );

MyHandler::eventFilter(...)
{
  //...
  case QDynamicPropertyChangeEvent:
    t.start();
    break;
  //...
}



XOO>Имеется в виду "наследование" изменения этой пропертии хотя бы. Саму пропертию можно задать на форме, она останется у объектов, а вот ее изменение приходится делать у каждого объекта, как теперь понимаю, без вариантов.


Я так понимаю, вам хочется селектор вида QPushPutton < MyMainWidget[style=1] — все кнопки на виджете, у которого проперти выставлена в 1. Такого не пробовал, ничего не скажу. Если заработает — то не будет никаких заморочек.

И да, сначала polish, потом unpolish. У вас наоборот было.
Re[6]: Style Sheet и Dynamic Properties
От: XOOIOOX  
Дата: 02.01.17 13:59
Оценка: 2 (1)
Здравствуйте, SaZ, Вы писали:

SaZ>
SaZ>auto buttons = rootWidget->findChildren<QPushButton *>();
SaZ>for ( const auto& button : buttons )
SaZ>  button->installEventFilter( myFilter );
SaZ>


Опаньки, про такую "рефлексию" я не знал. То, что нужно. Спасибо!

SaZ>Я так понимаю, вам хочется селектор вида QPushPutton < MyMainWidget[style=1] — все кнопки на виджете, у которого проперти выставлена в 1.


Не, это уже лишнее. Атрибут задан извне, просто при его смене меняю пропертии везде.

SaZ>У вас наоборот было.


Действительно. Спасибо!


UPD:

Отлично получилось. Именно так, как хотел. Красота:

void TEST0074::setProp(QWidget* obj, const char *name, const int prop)
{
    obj->setProperty(name, prop);
    obj->style()->polish(obj);
    obj->style()->unpolish(obj);
}

void TEST0074::state1()
{
    auto wgtList = this->findChildren<QWidget*>();
    for (const auto& wgt : wgtList) { setProp(wgt, "urgent", 1); }
}

void TEST0074::state2()
{
    auto wgtList = this->findChildren<QWidget*>();
    for (const auto& wgt : wgtList) { setProp(wgt, "urgent", 2); }
}

void TEST0074::state3()
{
    auto wgtList = this->findChildren<QWidget*>();
    for (const auto& wgt : wgtList) { setProp(wgt, "urgent", 0); }
}
Отредактировано 02.01.2017 14:18 XOOIOOX . Предыдущая версия .
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.