自定义的Qt仿示波器控件
此控件主要用来显示波形图。当用户不断向控件push数值时,图表中的波形逐渐向左移动。此类用法简单。先创建类实例,然后调用setLimit函数设置数据范围,调用setMaxCount函数设置控件显示数据的最大数量,最后不断向其push数据就行了。这个控件在VS2015和Qt5.9上测试通过。下面是控件的效果图,分别是数据未满和数据已满的截图:
下面上代码,头文件:
class MOscil : public QWidget { Q_OBJECT public: MOscil(QWidget* parent = nullptr); void setLimit(qreal min, qreal max); void setMaxCount(int count); void push(qreal value); private: void paintEvent(QPaintEvent *event) override; private: int maxCount; qreal minValue; qreal maxValue; QQueue<qreal> datas; };
CPP文件:
MOscil::MOscil(QWidget* parent) : QWidget(parent) { minValue = 0; maxValue = 100; maxCount = 10; } void MOscil::setLimit(qreal min, qreal max) { minValue = min; maxValue = max; update(); } void MOscil::setMaxCount(int count) { int dataCount = (int)datas.size(); if (count < dataCount) { const int delta = dataCount - count; for (int i = 0; i < delta; i++) { datas.pop_front(); } } maxCount = count; update(); } void MOscil::push(qreal value) { datas.append(value); if (datas.size() > maxCount) { datas.pop_front(); } update(); } void MOscil::paintEvent(QPaintEvent *event) { const int textPad = 20; const QMargins chartm(40, 20, 20, 20); QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing); int xLeft = chartm.left(); int xRight = width() - chartm.right(); int yTop = chartm.top(); int yBottom = height() - chartm.bottom(); /* 画矩形外框 */ painter.setBrush(Qt::NoBrush); painter.setPen(QColor(32, 243, 32)); painter.drawRect(xLeft, yTop, xRight - xLeft, yBottom - yTop); /* 画中间横竖虚线 */ painter.setPen(QPen(QColor(32, 173, 32), 1, Qt::DashLine)); for (int i = 0; i < 3; i++) { qreal y = yTop + (yBottom - yTop) / 4.0 * (i + 1); QPointF h1(xLeft, y); QPointF h2(xRight, y); painter.drawLine(h1, h2); qreal x = xLeft + (xRight - xLeft) / 4.0 * (i + 1); QPointF v1(x, yTop); QPointF v2(x, yBottom); painter.drawLine(v1, v2); } /* 画刻度数值 */ painter.setPen(Qt::black); QFontMetrics fm = painter.fontMetrics(); for (int i = 0; i <= 4; i++) { int y = yTop + (yBottom - yTop) / 4 * i; QString text = QString::number(maxValue + (minValue - maxValue) / 4 * i, 'g', 3); QPoint tpos(xLeft - textPad, y); QSize tsz = fm.size(0, text); painter.drawText(QRect(QPoint(tpos.x() - tsz.width() / 2, tpos.y() - tsz.height() / 2), tsz), text); } /* 画数据 */ int count = (int)datas.size(); qreal step = (xRight - xLeft) / (maxCount - 1.0); qreal startx = xLeft + step * (maxCount - count); painter.setPen(Qt::blue); for (int i = 1; i < count; i++) { qreal y1scr = yBottom + (yTop - yBottom) * (datas[i - 1] - minValue) / (maxValue - minValue); qreal y2scr = yBottom + (yTop - yBottom) * (datas[i] - minValue) / (maxValue - minValue); QPointF p1(startx, y1scr); QPointF p2(startx + step, y2scr); painter.drawLine(p1, p2); startx += step; } }