QCheckbox/QRadioButton line wrap Qt4.6.0

非 Y 不嫁゛ 提交于 2019-12-05 03:11:54
andref

That indeed is really annoying and cannot be solved without reimplementation: the label uses Qt::PlainText if I'm not mistaken. In our projects, the UI team solved this with two approaches.

Using the QRadioButton button as a title

Rewrite the QRadioButton text in such a fashion that it has only a brief description of the option. Put a QLabel underneath it and add a longer description. We use a smaller font and a little indentation to make it look neat. This is used frequently in Mac OS X, for example.

Removing the text from the radio button

Relayout the UI so that each radio button is put on the left of a QLabel. Add the whole text to the QLabel and set the label as the radio buttons' buddy. This is the least functional approach, because clicking the label does not check the radio button. Also, alignment is not very good.

The only way I know (but it's not "layoutable") is putting \n sign into a string.

I succeeded adding a layout and a label as a child for the radio button, and changing the vertical size policy to Preferred (instead of Fixed).

Unfortunately this didn't automatically make it react to the mouse hovers and clicks like the native label, but watch a hack: I setStyleSheet("border:none") for the radio button and it started working. Maybe that's some feature happening behind the scenes; I'd love to have some certainty.

And the indicator can be aligned using "QRadioButton::indicator{subcontrol-position:top left}" <- http://doc.trolltech.com/qq/qq20-qss.html

My solution:

#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
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!