Как нарисовать квадрат между текстом и флажком в QCheckBox

Мне нужно настроить QCheckbox как это: добавить квадрат между флажком и текстом пример:

Так что для этого я наследую QCheckBox и переопределить paintEvent(QPaintEvent*):

void customCheckBox::paintEvent(QPaintEvent*){
      QPainter p(this);
      QStyleOptionButton opt;
      initStyleOption(&opt);
      style()->drawControl(QStyle::CE_CheckBox,&opt,&p,this);

      QFontMetrics font= this->fontMetrics();// try to get pos by bounding rect of text, but it ain't work :p
      QRectF rec = font.boundingRect(this->text());
      p.fillRect(rect,QBrush(QColor(125,125,125,128)));
      p.drawRect(rect);

}

У меня есть проблема, что я не знаю, как место, чтобы разместить QRectF rec, И я не могу установить слишком маленький размер, например: он исчезнет, ​​когда размер rec

Любые идеи приветствуются.

PS: я использую OpenSUSE 13.1 с Qt 4.8.5

2 ответа

Решение

Основная идея заключается в том, чтобы скопировать реализацию по умолчанию для рисования флажков и изменить ее в соответствии с вашими потребностями. Мы получаем прямоугольник метки в реализации по умолчанию, поэтому нам просто нужно нарисовать новый элемент в этом месте и сместить метку вправо. Также нам нужно настроить подсказку по размеру, чтобы новый элемент и содержимое по умолчанию соответствовали минимальному размеру.

class CustomCheckBox : public QCheckBox {
  Q_OBJECT
public:
  CustomCheckBox(QWidget* parent = 0) : QCheckBox(parent) {
    m_decoratorSize = QSize(16, 16);
    m_decoratorMargin = 2;
  }

  QSize minimumSizeHint() const {
    QSize result = QCheckBox::minimumSizeHint();
    result.setWidth(result.width() + m_decoratorSize.width() + m_decoratorMargin * 2);
    return result;
  }

protected:
  void paintEvent(QPaintEvent*) {
    QPainter p(this);
    QStyleOptionButton opt;
    initStyleOption(&opt);
    QStyleOptionButton subopt = opt;
    subopt.rect = style()->subElementRect(QStyle::SE_CheckBoxIndicator, &opt, this);
    style()->drawPrimitive(QStyle::PE_IndicatorCheckBox, &subopt, &p, this);
    subopt.rect = style()->subElementRect(QStyle::SE_CheckBoxContents, &opt, this);
    p.fillRect(QRect(subopt.rect.topLeft() + QPoint(m_decoratorMargin, 0),
                     m_decoratorSize), QBrush(Qt::green));
    subopt.rect.translate(m_decoratorSize.width() + m_decoratorMargin * 2, 0);
    style()->drawControl(QStyle::CE_CheckBoxLabel, &subopt, &p, this);
    if (opt.state & QStyle::State_HasFocus) {
      QStyleOptionFocusRect fropt;
      fropt.rect = style()->subElementRect(QStyle::SE_CheckBoxFocusRect, &opt, this);
      fropt.rect.setRight(fropt.rect.right() + 
                          m_decoratorSize.width() + m_decoratorMargin * 2);
      style()->drawPrimitive(QStyle::PE_FrameFocusRect, &fropt, &p, this);
    }
  }

private:
  QSize m_decoratorSize;
  int m_decoratorMargin;
};

Обратите внимание, что это решение может быть непереносимым, потому что флажки нарисованы с существенными различиями на разных платформах. Я проверял это только на Windows. Я использовал реализацию по умолчанию, предоставленную QCommonStyle,

QAbstractButton имеет свойство под названием icon, который рисуется по-разному в зависимости от того, какой подкласс создан.

К счастью для вас, положение иконы в QCheckBox именно в том положении, которое вы проиллюстрировали на картинке

Итак, все что вам нужно сделать для вашего индивидуального QCheckBox это определить, какой значок должен быть и по умолчанию paintEvent позаботится об остальном.

Для простоты я предполагаю, что размер иконки должен быть таким же, как и сам флажок:

class CheckBox : public QCheckBox {
public:
    CheckBox() {
        QStyleOptionButton option;
        initStyleOption(&option);
        QSize indicatorSize = style()->proxy()->subElementRect(QStyle::SE_CheckBoxIndicator, &option, this).size();

        QPixmap pixmap(indicatorSize);
        pixmap.fill(Qt::green);

        QIcon icon;
        icon.addPixmap(pixmap);

        setIcon(icon);

    }
};

Я проверил это на компьютере с Windows 8.1 с Qt 5.2.1, и он работает.

Другие вопросы по тегам