Russian Qt Forum

Qt => Пользовательский интерфейс (GUI) => Тема начата: walk от Апрель 22, 2011, 16:12



Название: QPushButton с рельефным текстом
Отправлено: walk от Апрель 22, 2011, 16:12
Как сделать QPushButton с рельефным текстом? Вроде такого:


Название: Re: QPushButton с рельефным текстом
Отправлено: walk от Апрель 22, 2011, 16:16
Сам по себе bevelled текст можно создать, выводя белый текст, и поверх него чёрный, с небольшим отступом. Например, так удалось сделать bevelled label:

Код:
void BevelLabel::paintEvent(QPaintEvent *)
{
    QPainter p (this);
    p.setRenderHint(QPainter::Antialiasing);

    const QRect rect (this->rect().adjusted(0, 0, 0, 3));
    const Qt::Alignment align (Qt::AlignVCenter);

    QColor light (Qt::white);
    light.setAlphaF(0.375f);

    p.setPen(light);
    p.drawText(rect.adjusted(0, 1, 0, 1), align, text());

    p.setPen(Qt::black);
    p.drawText(rect, align, text());
}

С таким неидеальным, но приемлемым результатом:


Название: Re: QPushButton с рельефным текстом
Отправлено: walk от Апрель 22, 2011, 16:23
Но как это применить к QPushButton? Ведь текст там рисуется не просто так, а через QStyle::CE_PushButtonLabel. Нельзя потерять смещение текста кнопки вниз при нажатии. Поэтому примитивные трюки вроде размещения метки прямо на кнопке, или простого рисования в paintEvent, как предложено в теме HTML на QPushButton (http://www.prog.org.ru/topic_6457_0.html), здесь не проходят.

В QPushButton функция paintEvent выглядит так:

Код:
void QPushButton::paintEvent(QPaintEvent *)
{
    QStylePainter p(this);
    QStyleOptionButton option;
    initStyleOption(&option);
    p.drawControl(QStyle::CE_PushButton, option);
}

При этом документация утверждает, что QStyle::CE_PushButton означает последовательную отрисовку CE_PushButtonBevel, CE_PushButtonLabel и PE_FrameFocusRect.

Нельзя ли самостоятельно отрисовать дефолтно CE_PushButtonBevel и PE_FrameFocusRect, а CE_PushButtonLabel - дважды, меняя свойства QPainter?

Попробую такую идею: стилями задать текст кнопок белым; в paintEvent после стандартного кода вставить вывод чёрного текста на прозрачный QPixmap, и этот pixmap наложить при помощи QStylePainter::drawItemPixmap на уже нарисованный белый текст с нужным смещением; вертикальное смещение корректировать по свойству isDown, чтобы попадать в нажатие. Тут главная проблема - определить прямоугольник, в который выводится дефолтный текст.