单选按钮RadioButton

效果示例:

MRadioButton.h

//********************************************************
/// @brief 自定义单选按钮
/// @author y974183789@gmail.com
/// @date 2021/9/18
/// @note 支持自定义设置单选指示器位置
/// @version 1.0.0
//********************************************************

#pragma once

#include <QtWidgets/QRadioButton>

class MRadioButton : public QRadioButton {
    Q_OBJECT

public:
    //指示器位置,默认为左
    enum IndicatorPosition{
        kIndicatorLeft = 0,
        kIndicatorTop,
        kIndicatorRight,
        kIndicatorBottom,
        };

public:
    explicit MRadioButton(QWidget *parent = nullptr);

    ~MRadioButton() override;
    //设置指示器位置
    void setIndicatorPosition( IndicatorPosition pos);

protected:
    void paintEvent(QPaintEvent *e) Q_DECL_OVERRIDE;
    QSize sizeHint() const Q_DECL_OVERRIDE;
    bool hitButton(const QPoint &pos) const Q_DECL_OVERRIDE;

private:
    IndicatorPosition m_IndicatorPosition;
};

 MRadioButton.cpp

//********************************************************
/// @brief 自定义单选按钮
/// @author y974183789@gmail.com
/// @date 2021/9/18
/// @note 支持自定义设置单选指示器位置
/// @version 1.0.0
//********************************************************

#include "MRadioButton.h"
#include <QtWidgets/QStyleOptionButton>
#include <QtCore/qglobal.h>
#include <QtGui/QPainter>
#include <QtWidgets/QApplication>
#include <QtCore/QDebug>

#define INDICATOR_SPACING 4

MRadioButton::MRadioButton(QWidget *parent)
: QRadioButton(parent)
, m_IndicatorPosition(kIndicatorLeft)
{
}

MRadioButton::~MRadioButton()
{
}

void MRadioButton::setIndicatorPosition(IndicatorPosition pos)
{
    m_IndicatorPosition = pos;
}

void MRadioButton::paintEvent(QPaintEvent *e)
{
    if (kIndicatorLeft == m_IndicatorPosition)
    {
        return QRadioButton::paintEvent(e);
    }

    QWidget::paintEvent(e);

    QPainter p(this);
    QStyleOptionButton opt;
    initStyleOption(&opt);
    QRect rectIndicator;
    QRect rectLabel;
    auto alignment = Qt::AlignHCenter | Qt::AlignVCenter;

    auto pStyle = this->style();
    QRect indicator = opt.rect;
    indicator.setWidth(opt.iconSize.width());
    indicator.setHeight(opt.iconSize.height());
    int spacing = INDICATOR_SPACING;

    if(Q_NULLPTR != pStyle)
    {
        int h = pStyle->pixelMetric(QStyle::PM_IndicatorHeight, &opt, this);
        indicator.setRect(opt.rect.x(), opt.rect.y() + ((opt.rect.height() - h) / 2),
                          pStyle->pixelMetric(QStyle::PM_IndicatorWidth, &opt, this), h);
        indicator = pStyle->visualRect(opt.direction, opt.rect, indicator);
        spacing = pStyle->pixelMetric(QStyle::PM_CheckBoxLabelSpacing, &opt, this);
    }

    switch (m_IndicatorPosition)
    {
        case kIndicatorTop:
        {
            rectIndicator = QRect(QPoint(rect().center().x() - indicator.width() / 2,
                                         2), indicator.size());
            rectLabel = QRect(QPoint(rect().left(), rectIndicator.bottom() + INDICATOR_SPACING),
                              rect().bottomRight());
            break;
        }

        case kIndicatorRight:
        {
            alignment = Qt::AlignRight | Qt::AlignVCenter;
            rectIndicator = QRect(QPoint(rect().right() - indicator.width(), (rect().height() - indicator.height()) / 2), indicator.size());
            rectLabel = QRect(rect().topLeft(), QPoint(rectIndicator.left() - spacing,
                                                       rect().bottom()));
            break;
        }

        case kIndicatorBottom:
        {
            rectIndicator = QRect(QPoint(rect().center().x() - indicator.width() / 2, rect().bottom() - indicator.height() - INDICATOR_SPACING), indicator.size());
            rectLabel = QRect(rect().topLeft(), QPoint(rect().right(), rectIndicator.top() - INDICATOR_SPACING));
            break;
        }
        default:
            break;
    }

    //绘制指示器
    opt.rect = rectIndicator;
    style()->drawPrimitive(QStyle::PE_IndicatorRadioButton, &opt, &p, this);

    //绘制文本
    opt.rect = rectLabel;
    style()->drawItemText(&p, opt.rect, alignment | Qt::TextShowMnemonic,
                          opt.palette, opt.state & QStyle::State_Enabled, opt.text, QPalette::WindowText);
}

QSize MRadioButton::sizeHint() const
{
    if (kIndicatorLeft == m_IndicatorPosition
    || kIndicatorRight == m_IndicatorPosition)
    {
        return QRadioButton::sizeHint();
    }

    ensurePolished();
    QFontMetrics fm = fontMetrics();
    QStyleOptionButton opt;
    initStyleOption(&opt);
    QSize sz = style()->itemTextRect(fm, QRect(), Qt::TextShowMnemonic, false,text()).size();
    sz = QSize(qMax(sz.width(), opt.iconSize.width()), sz.height() + opt.iconSize.height() + INDICATOR_SPACING * 2);

    return style()->sizeFromContents(QStyle::CT_RadioButton, &opt, sz, this);
}

bool MRadioButton::hitButton(const QPoint &pos) const
{
    if (kIndicatorLeft == m_IndicatorPosition){
        return QRadioButton::hitButton(pos);
    }

    return rect().contains(pos);
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值