本例子是举例如何使用QT实现Android风格的开关控件,可以使用画颜色的方式,也可使用画图片方式。
一、运行效果
这是画颜色的方式,画图片的方式的运行效果这里不再展示
二、实现过程
要实现开关控件,我们需要按以下步骤进行实现
1. 数据定义QColor m_onColor; //开状态的颜色
QColor m_offColor; //关状态的颜色
bool m_Value; //开关值
int m_timerID; //移动定时器id
int m_offset; //移动过程中圆心的x坐标
bool m_isMove;
QPoint m_pressPos; //鼠标按下的位置
bool m_DisableVal;
QPixmap m_BkgPixmapNormal; //使用图片方式时保存开状态背景
QPixmap m_BkgPixmapPress; //使用图片方式时保存关状态背景
QPixmap m_ChunkPixmapNormal; //使用图片方式时保存开状态滑块
QPixmap m_ChunkPixmapPress;//使用图片方式时保存关状态滑块
2. 鼠标事件处理,这里只写出鼠标释放部分的代码if (m_isMove)
{
m_isMove = false;
m_offset = 0;
int xMove = event->pos().x()-m_pressPos.x();
if (abs(xMove) >= (this->rect().width()-this->rect().height())/2)
{
if (m_reverse)
{
if (xMove > 0 && m_Value)
{
setOnoffStatus(!m_Value);
emit valueChanged( m_Value);
}
else if (!m_Value)
{
setOnoffStatus(!m_Value);
emit valueChanged( m_Value);
}
else
{
update();
}
}
else
{
if (xMove
{
setOnoffStatus(!m_Value);
emit valueChanged( m_Value);
}
else if (!m_Value)
{
setOnoffStatus(!m_Value);
emit valueChanged( m_Value);
}
else
{
update();
}
}
}
else
{
update();
}
}
else
{
changeStatus(!m_Value);
}
3. 动画过渡过程处理if (m_reverse)
{
if (m_Value)
{
m_offset -= 8;
}
else
{
m_offset += 8;
}
}
else
{
if (m_Value)
{
m_offset += 8;
}
else
{
m_offset -= 8;
}
}
if ((m_offset <= this->rect().height()/2) || (m_offset >= (this->rect().width()-this->rect().height()/2)))
{
killTimer(m_timerID);
m_timerID = 0;
m_offset = 0;
}
update();
4. 根据各数据的值画出画面效果, 这里只展示部分代码//画关闭色
QPainterPath path;
QRectF mrect = QRect(rc.x()+1, rc.top()+margin+1, m_offset-1, margin*4);
path.moveTo(mrect.topRight() - QPointF(radius, 0));
path.lineTo(mrect.topLeft() + QPointF(radius, 0));
path.quadTo(mrect.topLeft(), mrect.topLeft() + QPointF(0, radius));
path.lineTo(mrect.bottomLeft() + QPointF(0, -radius));
path.quadTo(mrect.bottomLeft(), mrect.bottomLeft() + QPointF(radius, 0));
path.lineTo(mrect.bottomRight() - QPointF(radius, 0));
path.quadTo(mrect.bottomRight(), mrect.bottomRight() + QPointF(0, -radius));
path.lineTo(mrect.topRight() + QPointF(0, radius));
path.quadTo(mrect.topRight(), mrect.topRight() + QPointF(-radius, -0));
painter.setPen(QPen(QColor(70, 70, 70)));
painter.setBrush(QBrush(QColor(m_onColor.red()*2/3, m_onColor.green()*2/3, m_onColor.blue()*2/3)));
painter.fillPath(path, m_onColor);
painter.drawPath(path);
//画打开色
QPainterPath path2;
mrect = QRect(m_offset, rc.top()+margin+1, rc.width()-m_offset-1, margin*4);
path2.moveTo(mrect.topRight() - QPointF(radius, 0));
path2.lineTo(mrect.topLeft() + QPointF(radius, 0));
path2.quadTo(mrect.topLeft(), mrect.topLeft() + QPointF(0, radius));
path2.lineTo(mrect.bottomLeft() + QPointF(0, -radius));
path2.quadTo(mrect.bottomLeft(), mrect.bottomLeft() + QPointF(radius, 0));
path2.lineTo(mrect.bottomRight() - QPointF(radius, 0));
path2.quadTo(mrect.bottomRight(), mrect.bottomRight() + QPointF(0, -radius));
path2.lineTo(mrect.topRight() + QPointF(0, radius));
path2.quadTo(mrect.topRight(), mrect.topRight() + QPointF(-radius, -0));
painter.setPen(QPen(QColor(70, 70, 70)));
painter.setBrush(QBrush(QColor(m_offColor.red()*2/3, m_offColor.green()*2/3, m_offColor.blue()*2/3)));
painter.fillPath(path2, m_offColor);
painter.drawPath(path2);
//画圆圈
if (m_offset > rc.width()/2)
{
painter.setPen(QPen(QColor(70, 70, 70)));
painter.setBrush(QBrush(m_onColor));
painter.drawEllipse(rc.x()+m_offset-rc.height()/2, rc.top(), rc.height(), rc.height());
}
else
{
painter.setPen(QPen(QColor(70, 70, 70)));
painter.setBrush(QBrush(m_offColor));
painter.drawEllipse(rc.x()+m_offset-rc.height()/2, rc.top(), rc.height(), rc.height());
}
三、项目结构图
四、控件使用介绍
控件创建后可以使用以下两个函数改变控件开关状态的颜色/*set text on color*/
const QColor onColor() const;
void setOnColor(const QColor &data);
/*set text off color*/
const QColor offColor() const;
void setOffColor(const QColor &data);
如果要使用画图片的方式,可使用以下函数设置图片void setNormalBkgPix(const QPixmap &pix);//开状态背景
void setPressBkgPix(const QPixmap &pix); //关状态背景
void setNormalChunkPix(const QPixmap &pix); //开状态滑块
void setPressChunkPix(const QPixmap &pix); //关状态滑块