QStyle не подхватывает стили приложения
От: SaZ  
Дата: 02.10.13 14:03
Оценка:
Пытаюсь нарисовать чекбокс с помощью QStyle::drawPrimitive, но почему-то не подхватываются стили приложения.
На следующем скриншоте верхний чекбокс рисуется через QStyle::drawPrimitive, а нижний просто является виджетом (рисует сам себя)


Вот минимальный код, который воспроизводит проблему:
#include <QApplication>
#include <QWidget>
#include <QStyle>
#include <QPainter>
#include <QStyleOptionButton>
#include <QCheckBox>

class TestWindow
    : public QWidget
{
    Q_OBJECT

public:
    TestWindow() {}
    ~TestWindow() {}

    void paintEvent( QPaintEvent * event )
    {
        QPainter p( this );

        QStyleOptionButton opt;
        opt.state |= QStyle::State_On;
        opt.state |= QStyle::State_Enabled;
        opt.rect = QRect( 10, 10, 20, 20 );

        style()->drawPrimitive( QStyle::PE_IndicatorCheckBox, &opt, &p, this );
    }
};

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

    a.setStyleSheet( "QCheckBox::indicator{ border: 1px solid red; }" );

    TestWindow w;
    QCheckBox *cb = new QCheckBox( &w );
    cb->move( 10, 30 );

    w.show();

    return a.exec();
}

#include "main.moc"


Подскажите, в какую сторону копать, чтобы можно было рисовать чекбоксы с установленными в приложении стилями?

Qt 4.8.x, windows
qt qstyle qss
Re: QStyle не подхватывает стили приложения
От: sheep2k Россия  
Дата: 02.10.13 15:50
Оценка: 2 (1)
Здравствуйте, SaZ, Вы писали:

SaZ>Подскажите, в какую сторону копать, чтобы можно было рисовать чекбоксы с установленными в приложении стилями?


SaZ>Qt 4.8.x, windows


Скорее всего не получится пока. Тут написано:

Warning: Qt style sheets are currently not supported for custom QStyle subclasses. We plan to address this in some future release.

Re[2]: QStyle не подхватывает стили приложения
От: SaZ  
Дата: 02.10.13 16:21
Оценка:
Здравствуйте, sheep2k, Вы писали:

S>Скорее всего не получится пока. Тут написано:


Печалька. Я почему-то всегда думал, что Qt, когда парсит qss, создаёт на лету что-то типа QProxyStyle и им рисует все кастомные стили.

Ладно, придётся писать костыль через QPixmap::grabWidget
Re[2]: QStyle не подхватывает стили приложения
От: SaZ  
Дата: 02.10.13 16:33
Оценка:
Здравствуйте, sheep2k, Вы писали:

S>

S>Warning: Qt style sheets are currently not supported for custom QStyle subclasses. We plan to address this in some future release.


Глянул код, в проекте нигде QStyle / QProxyStyle не переопределяется.
Re: QStyle не подхватывает стили приложения
От: SaZ  
Дата: 02.10.13 17:01
Оценка:
Немного поэкспериментировал, как-то вообще оно странно работает ...

Цвета обрабатывает нормально (см. цвет стрелки комбика и цвет текста), бордюр, если задать для виджета, тоже устанавливается.

#include <QApplication>
#include <QWidget>
#include <QStyle>
#include <QPainter>
#include <QStyleOptionButton>
#include <QStyleOptionComboBox>

class TestWindow
    : public QWidget
{
    Q_OBJECT

public:
    TestWindow()
    {
        resize( 300, 200 );
    }

    ~TestWindow() {}

    void paintEvent( QPaintEvent * event )
    {
        QPainter p( this );

        const int xOfs = 10;
        int yOfs = 10;

        // Check box indicator
        {
            QStyleOptionButton opt;
            opt.state |= QStyle::State_On;
            opt.state |= QStyle::State_Enabled;
            opt.rect = QRect( xOfs, yOfs, 20, 20 );
            style()->drawPrimitive( QStyle::PE_IndicatorCheckBox, &opt, &p, this );
            yOfs += 20;
        }

        // Text
        {
            const QRect rc( xOfs, yOfs, 100, 20 );
            const Qt::ItemFlags f = Qt::AlignLeft | Qt::AlignVCenter | Qt::ItemIsEnabled;
            const bool isEnabled = f & Qt::ItemIsEnabled;
            const QString text = "Hello RSDN!";
            style()->drawItemText( &p, rc, f,  palette(), isEnabled, text );
            yOfs += 20;
        }

        // Button
        {
            QStyleOptionButton opt;
            opt.state |= QStyle::State_Enabled;
            opt.rect = QRect( xOfs, yOfs, 80, 25 );
            style()->drawControl( QStyle::CE_PushButton, &opt, &p, this );
            yOfs += 25;
        }

        // Combobox
        {
            QStyleOptionComboBox opt;
            opt.state |= QStyle::State_Enabled;
            opt.rect = QRect( xOfs, yOfs, 80, 25 );
            style()->drawComplexControl( QStyle::CC_ComboBox, &opt, &p, this );
            yOfs += 25;
        }

        // Check box indicator
        {
            QStyleOptionButton opt;
            opt.state |= QStyle::State_Enabled;
            opt.rect = QRect( xOfs, yOfs, 100, 20 );
            style()->drawControl( QStyle::CE_CheckBox, &opt, &p, this );
            yOfs += 20;
        }
    }
};

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

    const QString qss = 
        "QCheckBox::indicator { border: 1px solid red; }"
        "\n"
        "QWidget { color: green; }"
        "\n"
        "QWidget { border: 1px solid yellow; }"
        "";
    a.setStyleSheet( qss );

    TestWindow w;
    w.show();

    return a.exec();
}

#include "main.moc"
Re[3]: QStyle не подхватывает стили приложения
От: sheep2k Россия  
Дата: 02.10.13 17:58
Оценка:
Здравствуйте, SaZ, Вы писали:

SaZ>Здравствуйте, sheep2k, Вы писали:


S>>Скорее всего не получится пока. Тут написано:

SaZ>Печалька. Я почему-то всегда думал, что Qt, когда парсит qss, создаёт на лету что-то типа QProxyStyle и им рисует все кастомные стили.

Я могу залуждаться, но всё вроде правильно. drawPrimitive — низкий уровень, он обычно и используется при создании Custom Style. А вот drawControl и drawComplexControl вполне такие высокоуровневые, для них StyleSheet и учитывается, вполне возможно не полностью.
Ваш последний пример, вроде, как раз это и иллюстрирует.

Впрочем, ещё раз — я могу ошибаться, так далеко в потроха Qt я не лазил.
В последнем проекте, где переопределялось вообще всё визуальное представление, включая тени окон, я обошёлся только qss, ну и созданием ProxyStyle, чтобы убрать обрамление у контрола с фокусом, через qss это сделать невозможно.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.