Russian Qt Forum

Qt => Пользовательский интерфейс (GUI) => Тема начата: Serr500 от Август 21, 2012, 10:35



Название: [Решено] QToolButton и иконки
Отправлено: Serr500 от Август 21, 2012, 10:35
Имеется QToolButton (или QPushButton, что, я думаю, непринципиально). В ней есть текст и иконка. Нормальное поведение QPushButton таково, что центрируется текст вместе с иконкой, а QToolButton прижимает текст и иконку к левому краю. Требуется прижать иконку к левому краю, а текст выровнять по центру оставшегося пространства. Как это возможно сделать?
Заранее спасибо.


Название: Re: QToolButton и иконки
Отправлено: QtCoder от Август 21, 2012, 11:15
Переопределить paintEvent и рисовать отдельно иконку отдельно текст где захочется


Название: Re: QToolButton и иконки
Отправлено: Пантер от Август 21, 2012, 11:21
Поковыряй qss.


Название: Re: QToolButton и иконки
Отправлено: Serr500 от Август 21, 2012, 11:25
Переопределить paintEvent и рисовать отдельно иконку отдельно текст где захочется
Не хотелось бы так делать...  :(

Поковыряй qss.
А чуть точнее можно? Что именно там ковырять?  :-\ Стыдно признаться, но с QSS мне ни разу не приходилось сталкиваться.


Название: Re: QToolButton и иконки
Отправлено: Пантер от Август 21, 2012, 11:31
Глянул в справке, вроде, стилем не получится. Но я в стилях не силен, так что, спроси лучше у гугла.


Название: Re: QToolButton и иконки
Отправлено: Странник от Август 21, 2012, 11:33
в qss выравнивание текста и иконки совместно задается, насколько я помню, так что не вариант.


Название: Re: QToolButton и иконки
Отправлено: QtCoder от Август 21, 2012, 12:29
Переопределить paintEvent и рисовать отдельно иконку отдельно текст где захочется
Не хотелось бы так делать...  :(

Это идеологически самое верное решение.


Название: Re: QToolButton и иконки
Отправлено: Serr500 от Август 21, 2012, 12:40
Человек существо ленивое. Идеологически верное решение длинное и сложное. Гораздо проще пару строчек в стиле вписать. Но, похоже, придётся всё-таки создавать своего потомка кнопки с переопределённым paintEvent.


Название: Re: QToolButton и иконки
Отправлено: QtCoder от Август 21, 2012, 12:49
Человек существо ленивое. Идеологически верное решение длинное и сложное. Гораздо проще пару строчек в стиле вписать. Но, похоже, придётся всё-таки создавать своего потомка кнопки с переопределённым paintEvent.

Ленивому существу не место в программировании на Qt  :)


Название: Re: QToolButton и иконки
Отправлено: Serr500 от Август 21, 2012, 13:03
 :'( Пошёл пить йад...  :'(


Название: Re: QToolButton и иконки
Отправлено: porup от Август 21, 2012, 13:51
Ленивый вариант.

Код:
    QLabel *labelIcon = new QLabel(this);
    labelIcon->setPixmap(QPixmap(":/print24.png"));

    QHBoxLayout *layout = new QHBoxLayout;
    layout->addWidget(labelIcon);
    layout->addWidget(new QLabel("Print", this));

    ui->pushButton->setLayout(layout);


Название: Re: QToolButton и иконки
Отправлено: QtCoder от Август 21, 2012, 14:16
Ленивый вариант.

Код:
    QLabel *labelIcon = new QLabel(this);
    labelIcon->setPixmap(QPixmap(":/print24.png"));

    QHBoxLayout *layout = new QHBoxLayout;
    layout->addWidget(labelIcon);
    layout->addWidget(new QLabel("Print", this));

    ui->pushButton->setLayout(layout);

Что-то текст на картинке не по центру кнопки. Он естессно по центру второго label.


Название: Re: QToolButton и иконки
Отправлено: torwig от Август 21, 2012, 15:20
Может пробелы перед текстом добавлять?) Но это если фикс размер, а так кривовато)
Две QLabel неплохо, но может лучше две QPushButton? Но в этом случае с обработкой клика надо будет чуточку посидеть, чтобы и кликалось как одно целое и все такое.


Название: Re: QToolButton и иконки
Отправлено: Serr500 от Август 21, 2012, 15:28
Ленивый вариант.
Выглядит красиво... Но ещё придётся добавлять функциональность кнопки.

Что-то текст на картинке не по центру кнопки. Он естессно по центру второго label.
Мне именно так и надо - центрировать текст по свободному от иконки пространству.

Может пробелы перед текстом добавлять?) Но это если фикс размер, а так кривовато)
Размер нефиксированный. Кнопка может непредсказуемо растягиваться.

Две QLabel неплохо, но может лучше две QPushButton? Но в этом случае с обработкой клика надо будет чуточку посидеть, чтобы и кликалось как одно целое и все такое.
... и ещё чтобы выглядело как одна кнопка и вид не отличался.

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

Вобщем, всем спасибо. Пошёл кодить paintEvent.


Название: Re: QToolButton и иконки
Отправлено: sudo от Август 21, 2012, 16:09
Ленивому существу не место в программировании на Qt  :)

Неленивому существу вообще не место в программировании :D Не было бы ленивых программистов, не было бы ничего :D


Название: Re: QToolButton и иконки
Отправлено: QtCoder от Август 22, 2012, 07:58
Идеологически верный вариант
Код
C++ (Qt)
void ToolButton::paintEvent(QPaintEvent * event)
{
  QToolButton::paintEvent(event);
  QPainter painter(this);
 
  QRect rect = event->rect();
  QTextOption opt;
  opt.setAlignment(Qt::AlignCenter);
  painter.drawText(rect, text_, opt);
 
  int y = qAbs(rect.height() - pixmap_.height()) / 2;
  const int x = 6;
  painter.drawPixmap(x, y, pixmap_);
}

Вверху ToolButton, снизу QToolButton


Название: Re: QToolButton и иконки
Отправлено: Kurles от Август 22, 2012, 08:29
Идеологически верный вариант
Код
C++ (Qt)
void ToolButton::paintEvent(QPaintEvent * event)
{
  QToolButton::paintEvent(event);
  QPainter painter(this);
 
  QRect rect = event->rect();
  QTextOption opt;
  opt.setAlignment(Qt::AlignCenter);
  painter.drawText(rect, text_, opt);
 
  int y = qAbs(rect.height() - pixmap_.height()) / 2;
  const int x = 6;
  painter.drawPixmap(x, y, pixmap_);
}

Вверху ToolButton, снизу QToolButton

м-да, а столько времени на разговоры было потрачено )))


Название: Re: QToolButton и иконки
Отправлено: Serr500 от Август 22, 2012, 10:18
Идеологически верный вариант у меня почему-то не работает.

Верхняя картинка - с QPushButton::paintEvent, нижняя - без.


Название: Re: QToolButton и иконки
Отправлено: QtCoder от Август 22, 2012, 10:26
Идеологически верный вариант у меня почему-то не работает.

Верхняя картинка - с QPushButton::paintEvent, нижняя - без.

Картинки и текст надо передавать своими функциями. Не использовать setText и setIcon.
Вызов родительского paintEvent отрисует кнопку без иконки и тектса, а затем уже по ней рисуем нашу картинку и текст. Очевидно, же.
Код
C++ (Qt)
  ToolButton * tb = new ToolButton(this);
  tb->setDrawPixmap(QPixmap(":/images/new.png"));
  tb->setDrawText("Test");
 


Название: Re: QToolButton и иконки
Отправлено: Serr500 от Август 22, 2012, 10:34
Тьфу, блин!  >:( Действительно.  :( Извиняюсь за тупость.   :-\


Название: Re: QToolButton и иконки
Отправлено: Serr500 от Август 22, 2012, 11:06
Небольшое изучение исходников Qt и нежелание создавать отдельные поля и методы нового объекта привели к созданию следующего кода:

Код:
void QPushButtonPlus::paintEvent(QPaintEvent *event)
{
    QStylePainter StylePainter(this);
    QStyleOptionButton StyleOption;
    initStyleOption(&StyleOption);
    StyleOption.text.clear();
    StyleOption.icon = QIcon();

    StylePainter.drawControl(QStyle::CE_PushButton, StyleOption);

    QRect Rect = event->rect();
    QTextOption TextOption;
    TextOption.setAlignment(Qt::AlignCenter);
    StylePainter.drawText(Rect, text(), TextOption);

    QPixmap Pixmap = icon().pixmap(iconSize());
    int y = qAbs(Rect.height() - Pixmap.height()) / 2;
    const int x = 6;
    StylePainter.drawPixmap(x, y, Pixmap);
}
Огромное спасибо QtCoder за помощь.


Название: Re: QToolButton и иконки
Отправлено: QtCoder от Август 22, 2012, 12:18
Небольшое изучение исходников Qt и нежелание создавать отдельные поля и методы нового объекта привели к созданию следующего кода:

Код:
void QPushButtonPlus::paintEvent(QPaintEvent *event)
{
    QStylePainter StylePainter(this);
    QStyleOptionButton StyleOption;
    initStyleOption(&StyleOption);
    StyleOption.text.clear();
    StyleOption.icon = QIcon();

    StylePainter.drawControl(QStyle::CE_PushButton, StyleOption);

    QRect Rect = event->rect();
    QTextOption TextOption;
    TextOption.setAlignment(Qt::AlignCenter);
    StylePainter.drawText(Rect, text(), TextOption);

    QPixmap Pixmap = icon().pixmap(iconSize());
    int y = qAbs(Rect.height() - Pixmap.height()) / 2;
    const int x = 6;
    StylePainter.drawPixmap(x, y, Pixmap);
}
Огромное спасибо QtCoder за помощь.

Всё хорошо, теперь подумай, что произойдет если размер иконки будет больше размера кнопки.


Название: Re: [Решено] QToolButton и иконки
Отправлено: Serr500 от Август 22, 2012, 13:28
Всё нормально будет. Сейчас проверил. Кнопка увеличивается в размерах чтобы вместить иконку.


Название: Re: [Решено] QToolButton и иконки
Отправлено: QtCoder от Август 22, 2012, 13:31
Всё нормально будет. Сейчас проверил. Кнопка увеличивается в размерах чтобы вместить иконку.

А ну понятно, ты же ставишь setIcon вот оно и увеличивает. В моем примере бы обрезалось.


Название: Re: [Решено] QToolButton и иконки
Отправлено: Serr500 от Август 22, 2012, 15:34
Допилил обработчик. Убрал "магическое число" 6, заставив вытаскивать маргины из стиля. И сделал выравнивание текста не по центру кнопки, а по центру свободного от иконки пространства. Вот что получилось:
Код:
void QPushButtonPlus::paintEvent(QPaintEvent *)
{
    // Основа кнопки.
    QStylePainter StylePainter(this);
    QStyleOptionButton StyleOption;
    initStyleOption(&StyleOption);
    StyleOption.text.clear();
    StyleOption.icon = QIcon();
    StylePainter.drawControl(QStyle::CE_PushButton, StyleOption);

    // Прямоугольник для рисования содержимого.
    QRect SubRect = style()->subElementRect(QStyle::SE_PushButtonContents, &StyleOption, this);

    // Иконка.
    if (!icon().isNull()) {
        QPixmap Pixmap = icon().pixmap(iconSize());
        int y = (SubRect.height() - Pixmap.height()) / 2;
        StylePainter.drawPixmap(SubRect.x(), SubRect.y() + y, Pixmap);
        SubRect.setX(Pixmap.width() + 2* SubRect.x());
    }

    // Текст.
    if (!text().isEmpty()) {
        QTextOption TextOption;
        TextOption.setAlignment(Qt::AlignCenter);
        StylePainter.drawText(SubRect, text(), TextOption);
    }
}