
如今,很多智能手机上都提供了非常漂亮的控件,用来实现特定的人机交互功能。比如本题所述的液位控件,它采用拟物化的方式,以波浪液位指示数值的大小。如果在PC上也能使用这种控件该多好啊。网上目前能找到的类似控件,要么不能跨平台,要么是闭源的,因此,还是自己开发一款液位控件才方便。
本液位控件基于Qt 5开发。开发这样一个液位控件分为如下几个步骤:
· 设置剪裁形状(矩形/椭圆)。
· 绘制背景。
· 绘制双层波浪液位。
· 绘制前景边框。
· 绘制百分比文本。
下面进行详细介绍。
1.设置剪裁形状(矩形/椭圆)
设置剪裁形状,主要是设置液位控件的外观为矩形还是椭圆。
void CWaveWidget::drawClipPath(QPainter* painter) {
QPainterPath clipPath;
if (m_bClipPathEllipse) {
clipPath.addEllipse(this->rect());
}
else {
clipPath.addRoundedRect(this->rect(), m_radius, m_radius);
}
painter->setClipPath(clipPath);
}
2.绘制背景
绘制背景,指的是绘制波浪后面的背景部分。
void CWaveWidget::drawBackground(QPainter* painter) {
painter->setBrush(m_backgroundBrush);
painter->drawRect(this->rect());
}
3.绘制双层波浪液位
波浪液位部分的绘制如代码清单1-1所示。波浪采用QPainterPath进行绘制,用正弦波来表示波浪,再加上线段从而连接成封闭区域,见标号①处。在绘制波浪时,应先绘制后方波浪,再绘制前方波浪,见标号②处。
代码清单1-1
void CWaveWidget::drawWater(QPainter* painter) {
int startX = 0;
int startY = 0;
int endX = this->width();
int endY = this->height();
float height = endY - (float)endY*(this->m_fValue / 100);
QPainterPath waterPathFront;
waterPathFront.moveTo(startX, endY);
QPainterPath waterPathBack;
waterPathBack.moveTo(startX, endY);
for (int i = 0; i <= endX; i++) {
float y1, y2;
y1 = 15 * qSin(0.035*i + m_offset) + height; // 前方波浪(正弦函数)①
y2 = 15 * qSin(0.035*i + 30+ m_offset) + height; // 后方波浪(正弦函数)
if (qAbs(m_fValue) < C_DELTA) { // 极数处理
y1 = y2 = endY;
}
if (qAbs(m_fValue-100.) < C_DELTA) {// 极数处理
y1 = y2 = 0;
}
waterPathFront.lineTo(i, y1);
waterPathBack.lineTo(i, y2);
}
waterPathFront.lineTo(endX, endY);
waterPathBack.lineTo(endX, endY);
painter->save();
painter->setPen(Qt::NoPen);
painter->setBrush(m_waveBrush2);
painter->drawPath(waterPathBack); ②
painter->setBrush(m_waveBrush);
painter->drawPath(waterPathFront);
painter->restore();
}
4.绘制前景边框
为了美观,可以为液位控件绘制前景的边框。
void CWaveWidget::drawForeground(QPainter* painter) {
painter->setCompositionMode(QPainter::CompositionMode_SourceIn);
QPen pn(m_frameColor);
pn.setWidthF(m_frameWidth);
painter->setPen(pn);
painter->setBrush(Qt::NoBrush);
if (m_bClipPathEllipse) {
painter->drawEllipse(this->rect());
}
else {
painter->drawRoundedRect(this->rect(), m_radius, m_radius);
}
}
5.绘制百分比文本
最后,为了指示液位的具体数值,还需要绘制百分比文本,见代码清单1-2。
代码清单1-2
void CWaveWidget::drawForeground(QPainter* painter) {
QPen pn(m_frameColor);
pn.setWidthF(m_frameWidth);
painter->setPen(pn);
painter->setBrush(Qt::NoBrush);
if (m_bClipPathEllipse) {
painter->drawEllipse(this->rect());
}
else {
painter->drawRoundedRect(this->rect(), m_radius, m_radius);
}
}
这样,一款液位控件就开发完成了。为了节省篇幅,将CWaveWidget的接口省略。对源代码感兴趣的朋友可以关注微信公众号[软件特攻队],回复: qx0002。