QT自定义控件--滑动按钮
原创
©著作权归作者所有:来自51CTO博客作者贝勒里恩的原创作品,请联系作者获取转载授权,否则将追究法律责任
文章目录
一、效果展示
二、绘制过程
2.1、控件分析
滑动按钮主要由背景框和滑块组成。当点击按钮的时候,滑块就会滑到另一边,相应的背景框和滑块的颜色都会发生切换,所以可以将任务细分为三个:绘制背景框、绘制滑块、实现点击滑动。
2.2、原理详解
滑动按键的功能是:点击按钮时,滑块会滑动到另一边;为了捕捉点击动作就必须写一个按钮点击事件mousePressEvent()
。为了实现滑块平滑的移动,可以使用定时器逐次移动(例如每10ms移动1/50的移动距离)。产生点击之后,将按钮的状态翻转,再计算出滑块的目标位置,并开启定时器实现逐次移动,移动要根据滑块的初始位置和目标位置来判断:当开关关闭时发生点击,滑块要向右滑动,初始位置+=移动步长,直到初始位置等于目标位置;当开关开启时发生点击,滑块要向左滑动,初始位置-=移动步长,直到初始位置等于目标位置。然后每次定时器计时到达就触发重绘事件,因为绘制滑块时会参考初始位置,所以就实现了滑块平滑的移动。
2.3、绘制背景框
void SwitchButton::drawBg(QPainter *painter)
{
painter->save();
painter->setPen(Qt::NoPen);
if (!checked)
{
painter->setBrush(bgColorOff);
}
else
{
painter->setBrush(bgColorOn);
}
painter->drawRoundedRect(rect(), rectRadius, rectRadius);
painter->restore();
}
2.4、绘制滑块
void SwitchButton::drawSlider(QPainter *painter)
{
painter->save();
painter->setPen(Qt::NoPen);
if (!checked) {
painter->setBrush(sliderColorOff);
} else {
painter->setBrush(sliderColorOn);
}
int sliderWidth = width() / 2 - space * 2;
int sliderHeight = height() - space * 2;
QRect sliderRect(startX + space, space, sliderWidth , sliderHeight);
painter->drawRoundedRect(sliderRect, rectRadius, rectRadius);
painter->restore();
}
2.5、其余代码
SwitchButton::SwitchButton(QWidget *parent): QWidget(parent)
{
checked = false;
//开、闭时背景颜色
bgColorOff = QColor(225, 225, 225);
bgColorOn = QColor(250, 250, 250);
//开、闭时滑块颜色
sliderColorOff = QColor(100, 100, 100);
sliderColorOn = QColor(100, 184, 255);
space = 2; //背景间隔
rectRadius = 5;
step = width() / 50; //步长
//起始、目标位置
startX = 0;
endX = 0;
timer = new QTimer(this);
timer->setInterval(10);
connect(timer, SIGNAL(timeout()), this, SLOT(updateValue()));
setFont(QFont("Microsoft Yahei", 10));
}
void SwitchButton::mousePressEvent(QMouseEvent *)
{
checked = !checked;
emit checkedChanged(checked);
//每次移动的步长为宽度的 50分之一
step = width() / 50;
//状态切换改变后自动计算终点坐标
if (checked)
{
endX = width() - width() / 2;
}
else
{
endX = 0;
}
timer->start();
}
void SwitchButton::updateValue()
{
if (checked) {
if (startX < endX) {
startX = startX + step;
} else {
startX = endX;
timer->stop();
}
} else {
if (startX > endX) {
startX = startX - step;
} else {
startX = endX;
timer->stop();
}
}
update();
}
void SwitchButton::resizeEvent(QResizeEvent *)
{
//每次移动的步长为宽度的 50分之一
step = width() / 50;
//尺寸大小改变后自动设置起点坐标为终点
if (checked)
{
startX = width() - width() / 2;
}
else
{
startX = 0;
}
update();
}
void SwitchButton::paintEvent(QPaintEvent *)
{
//绘制准备工作,启用反锯齿
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
//绘制背景
drawBg(&painter);
//绘制滑块
drawSlider(&painter);
}