Перенос строки QCheckbox/QRadioButton Qt4.6.0

Я пытаюсь использовать многострочный флажок/переключатель с Qt, используя стандартный QCheckbox/QRadioButton.

Я не нашел прямого решения, так как QRadioButton{wrap:true;} не действует. Единственное, что возможно, это получить доступ к QRadioButton->label->setLineWrap(true), но

  1. Я хотел бы сделать это от дизайнера
  2. не нужно переписывать виджет

Любая идея, кроме размещения QRadioButton и QLabel рядом друг с другом?

Спасибо, Борис.


person Boris Gougeon    schedule 03.12.2009    source источник


Ответы (4)


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

Использование кнопки QRadioButton в качестве заголовка

Макет с использованием QRadioButton в качестве заголовка

Перепишите текст QRadioButton таким образом, чтобы в нем было только краткое описание параметра. Поместите QLabel под ним и добавьте более длинное описание. Мы используем меньший шрифт и небольшой отступ, чтобы он выглядел аккуратно. Это часто используется, например, в Mac OS X.

Удаление текста из переключателя

Макет с использованием ярлыков друзей

Измените макет пользовательского интерфейса так, чтобы каждый переключатель располагался слева от QLabel. Добавьте весь текст в QLabel и установите метку в качестве приятеля переключателей. Это наименее функциональный подход, потому что щелчок по метке не включает переключатель. Кроме того, выравнивание не очень хорошее.

person andref    schedule 06.12.2009
comment
Спасибо за Ваш ответ. Я решил свою проблему с помощью второго решения, которое вы объяснили. Это не очень хорошо в макете, но работает... Я очень надеюсь, что Qt решит эту проблему в ближайшем будущем! Спасибо еще раз в любом случае. - person Boris Gougeon; 07.12.2009

Единственный способ, который я знаю (но это не «макет»), - это поместить знак \n в строку.

person Kamil Klimek    schedule 03.12.2009

Мне удалось добавить макет и метку в качестве дочернего элемента для переключателя и изменить политику вертикального размера на Preferred (вместо Fixed).

К сожалению, это не заставляло его автоматически реагировать на наведения и щелчки мыши, как нативная метка, но посмотрите на хак: я установилStyleSheet("border:none") для переключателя, и он начал работать. Может быть, это какая-то особенность, происходящая за кулисами; Я хотел бы иметь некоторую уверенность.

И индикатор можно выровнять с помощью "QRadioButton::indicator{subcontrol-position:top left}" ‹- http://doc.trolltech.com/qq/qq20-qss.html

person ulzha    schedule 29.12.2009

Мое решение:

#ifndef CHECKBOX_H
#define CHECKBOX_H

#include <QCheckBox>

#include <QHBoxLayout>
#include <QLabel>

class CheckBox : public QCheckBox
{
    Q_OBJECT
public:
   explicit CheckBox(QWidget *parent = 0);

   void setText(const QString & text);
   QSize sizeHint() const;
   bool hitButton(const QPoint &pos) const;

protected:
   void paintEvent(QPaintEvent *);

private:
   QHBoxLayout* _layout;
   QLabel*      _label;
};

#endif // CHECKBOX_H




#include "checkbox.h"

#include <QStylePainter>
#include <QStyleOption>

#define MARGIN 4 // hardcoded spacing acording to QCommonStyle implementation

CheckBox::CheckBox(QWidget *parent) : QCheckBox(parent)
{
    setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred, QSizePolicy::CheckBox));

    QStyleOptionButton opt;
    initStyleOption(&opt);

    QRect label_rect = style()->subElementRect(QStyle::SE_CheckBoxContents, &opt, this);

    _label = new QLabel(this);
    _label->setWordWrap(true);
    _label->setMouseTracking(true);
    //_label->setMinimumHeight(label_rect.height());

    _layout = new QHBoxLayout(this);
    _layout->setContentsMargins(label_rect.left()+MARGIN, MARGIN/2, MARGIN/2, MARGIN/2);
    _layout->setSpacing(0);
    _layout->addWidget(_label);

    setLayout(_layout);
}

void CheckBox::setText(const QString & text)
{
    _label->setText(text);
    QCheckBox::setText(text);
}

void CheckBox::paintEvent(QPaintEvent *)
{
    QStylePainter p(this);
    QStyleOptionButton opt;
    initStyleOption(&opt);

    QStyleOptionButton subopt = opt;
    subopt.rect = style()->subElementRect(QStyle::SE_CheckBoxIndicator, &opt, this);
    subopt.rect.moveTop(opt.rect.top()+MARGIN/2); // align indicator to top

    style()->proxy()->drawPrimitive(QStyle::PE_IndicatorCheckBox, &subopt, &p, this);

    if (opt.state & QStyle::State_HasFocus)
    {
        QStyleOptionFocusRect fropt;
        fropt.QStyleOption::operator=(opt);
        fropt.rect = style()->subElementRect(QStyle::SE_CheckBoxFocusRect, &opt, this);
        style()->proxy()->drawPrimitive(QStyle::PE_FrameFocusRect, &fropt, &p, this);
    }
}

QSize CheckBox::sizeHint() const
{
    return QSize(); // will be calculated by layout
}

bool CheckBox::hitButton(const QPoint &pos) const
{
    QStyleOptionButton opt;
    initStyleOption(&opt);
    return opt.rect.contains(pos); // hit all button
}
person Andrei Andreev    schedule 03.09.2015
comment
Начало решения вполне нормальное. Однако алгоритм вычисления прямоугольника фокуса должен быть улучшен (т.е. fropt.rect = style()->subElementRect(QStyle::SE_CheckBoxFocusRect, &opt, this);), так как прямоугольник фокуса будет путаться с многострочным текстом, а не окружать Это. Чтобы гарантировать, что система нарисует красивый прямоугольник фокуса для такой проблемы, вам необходимо установить правильную высоту для такого прямоугольника, поскольку многострочный текст имеет разную высоту. - person Vaidotas Strazdas; 07.03.2019