效果示例:
MRadioButton.h
//********************************************************/// @brief 自定义单选按钮/// @author y974183789@/// @date /9/18/// @note 支持自定义设置单选指示器位置/// @version 1.0.0//********************************************************#pragma once#include <QtWidgets/QRadioButton>class MRadioButton : public QRadioButton {Q_OBJECTpublic://指示器位置,默认为左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@/// @date /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 4MRadioButton::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);}