1 概述
由于 Qt 的 widgets 模块没有提供类似开关一样的按钮,所以采用继承自
QWidget类实现一个自绘的开关按钮。
开发环境
- 系统:Window10
- Qt版本:5.14.2
- 编译器:MinGW_64/MSVC 2017
2 实现效果

3 实现步骤
3.1 添加继承自QWidget的类
SwitchButton类头文件定义
class SwitchButton : public QWidget
{
Q_OBJECT
public:
enum SwitchState
{
SS_On,
SS_Off
};
explicit SwitchButton(QWidget *parent = nullptr);
SwitchState switchState() const { return m_currentState; }
void setSwitchState(SwitchState state);
protected:
void paintEvent(QPaintEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
private:
SwitchState m_currentState;
QColor m_color;
};
SwitchButton类源文件定义
SwitchButton::SwitchButton(QWidget *parent)
: QWidget{parent}
{
m_currentState = SS_Off;
m_color = QColor(140, 150, 175);
setFixedSize(40, 20);
setCursor(Qt::PointingHandCursor);
}
void SwitchButton::setSwitchState(SwitchState state)
{
m_currentState = state;
update();
}
void SwitchButton::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event)
QPainter p(this);
p.setRenderHint(QPainter::Antialiasing);
p.setPen(Qt::NoPen);
p.save();
if (m_currentState == SS_On) {
m_color = QColor(65, 127, 249);
} else {
m_color = QColor(140, 150, 175);
}
p.setBrush(m_color);
qreal radius = rect().height() / 2;
p.drawRoundedRect(rect(), radius, radius);
p.restore();
p.setBrush(Qt::white);
qreal edge = height() - 4;
if (m_currentState == SS_Off) {
p.drawEllipse(QRectF(2.0, 2.0, edge, edge));
} else {
p.drawEllipse(QRectF(qreal(width() - edge - 2), 2.0, edge, edge));
}
}
void SwitchButton::mouseReleaseEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton) {
if (m_currentState == SS_Off) {
m_currentState = SS_On;
update();
} else {
m_currentState = SS_Off;
update();
}
}
QWidget::mouseReleaseEvent(event);
}
3.2 说明
- 此例子没有对SwitchButton控件的大小实现自适应功能,只有固定尺寸40X20。
- 可以在此基础上加上动画,效果会更好些。
该文章介绍如何在Qt环境中,通过继承QWidget类并重写paintEvent和mouseReleaseEvent方法,实现一个自定义的开关按钮。开发者定义了SwitchState枚举来表示开关状态,并提供了设置和获取开关状态的方法。示例代码中,按钮尺寸固定,未实现大小自适应,但提到了可进一步添加动画效果。
2586





