本人使用QPainter自绘了一个圆盘图,下面这张图片为效果图
图片中的所有(圆、刻度线、字体)均为自绘,没有使用图片
使用方法:在Ui中拖拽一个widget控件,然后右键点击该widget控件,选择提升。
话不多说,直接上代码
头文件qdiscwidget.h
#ifndef QDISCWIDGET_H
#define QDISCWIDGET_H
#include <QWidget>
#include <QPainter>
#include <QPen>
#include <QMouseEvent>
#include <QtMath>
#include <QLabel>
#include <QPushButton>
#include <QVector>
#include <QMutableVectorIterator>
#include <QtDataVisualization>
class QDiscWidget : public QWidget
{
Q_OBJECT
public:
explicit QDiscWidget(QWidget *parent = 0);
~QDiscWidget();
protected:
void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE;
void mousePressEvent(QMouseEvent *event) override;
void mouseMoveEvent(QMouseEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
void resizeEvent(QResizeEvent *event) override;
void enterEvent(QEvent *event) override;
void leaveEvent(QEvent *event) override;
private slots:
void on_timeout();
private:
int side; //表示宽,高中较小的
int disc_R; //圆盘半径
int W, H; //控件的宽高
bool showYellowLine; //是否显示黄线
bool showRedLine; //是否显示红线
QPointF yellowLinePoint, redLinePoint, pressPoint; //记录移动中黄线、红线的点,以及鼠标按下的点 //表示信号的点,以及信号消失的点
qreal point_R; //点的半径
int nNum; //控制显示Label的个数
qreal yLineAg; //线所在的角度
void initWidget();
void initPara();
private:
void draw_disc_scale(QPainter &p);
void draw_disc_text(QPainter &p);
void draw_line_scale(QPainter &p);
void draw_arc(QPainter &p);
void fill_Gradient_color(QPainter &p);
void draw_moveable_yline(QPainter &p);
void draw_moveable_rline(QPainter &p);
void draw_press_line(QPainter &p);
signals:
void showAngle(qreal dieangle, qreal elvangle);
};
#endif // QDISCWIDGET_H
源文件qdiscwidget.cpp
#if _MSC_VER >= 1600
#pragma execution_character_set("utf-8")
#endif
#include "qdiscwidget.h"
QDiscWidget::QDiscWidget(QWidget *parent) : QWidget(parent)
{
initWidget();
initPara();
QTimer *timer = new QTimer(this);
timer->start(50);
connect(timer, SIGNAL(timeout()), this, SLOT(on_timeout()));
}
QDiscWidget::~QDiscWidget()
{
}
//初始化控件
void QDiscWidget::initWidget()
{
setPalette(QPalette(QColor(13, 46, 62)));//设置背景色
// setPalette(QPalette(QColor(0, 0, 0)));
setAutoFillBackground(true);
setMouseTracking(true);
}
//初始化参数
void QDiscWidget::initPara()
{
disc_R = 93;
point_R = 0.8;
showYellowLine = true;
showRedLine = false;
}
void QDiscWidget::paintEvent(QPaintEvent *event)
{
//side = (width() > height()) ? height() : width();
side = qMin(W, H);
QPainter painter(this);
QRect rect((W-side)/2, (H-side)/2, side, side);
painter.setViewport(rect);
painter.setWindow(-100, -100, 200, 200);
painter.setRenderHints(QPainter::TextAntialiasing | QPainter::Antialiasing); // 启用反锯齿
draw_disc_scale(painter);
draw_disc_text(painter);
draw_line_scale(painter);
draw_arc(painter);
fill_Gradient_color(painter);
draw_moveable_yline(painter);
draw_moveable_rline(painter);
draw_press_line(painter);
}
void QDiscWidget::mousePressEvent(QMouseEvent * event)
{
qreal pointX = event->x() - W / 2;
qreal pointY = event->y() - H / 2;
if(showRedLine && !showYellowLine)
{
showRedLine = false;
return;
}
if(showYellowLine && !showRedLine && !redLinePoint.isNull())
{
showYellowLine = false;
return;
}
if(showYellowLine && !showRedLine)
{
//将按下的点的坐标转换为圆上的点(即距离圆心为半径)
pressPoint = QPointF(pointX * disc_R / qSqrt(pointX * pointX + pointY * pointY), pointY * disc_R / qSqrt(pointX * pointX + pointY * pointY));
}
//当黄线和红线都不能移动时,判断目前按下的点距离哪条线更近一点,并让其可移动
if(!showRedLine && !showYellowLine)
{
QPointF point = QPointF(pointX * disc_R / qSqrt(pointX * pointX + pointY * pointY), pointY * disc_R / qSqrt(pointX * pointX + pointY * pointY));
qreal dst1 = qPow((point.x() - yellowLinePoint.x()),2) + qPow((point.y() - yellowLinePoint.y()),2);
qreal dst2 = qPow((point.x() - redLinePoint.x()),2) + qPow((point.y() - redLinePoint.y()),2);
if(dst1<dst2)
{
showYellowLine = true;
}
if(dst1>dst2)
{
showRedLine = true;
}
}
}
void QDiscWidget::enterEvent(QEvent *event)
{
// QWidget::enterEvent(event);
//设置鼠标的形状为十字星
setCursor(Qt::CrossCursor);
}
void QDiscWidget::leaveEvent(QEvent *event)
{
//恢复鼠标的形状
setCursor(Qt::CustomCursor);
QWidget::leaveEvent(event);
}
void QDiscWidget::mouseMoveEvent(QMouseEvent * event)
{
qreal pointX = event->x() - W / 2;
qreal pointY = event->y() - H / 2;
//计算出当前可移动的线所在的角度(0~360)
yLineAg = qAsin(pointX/qSqrt(pointX * pointX + pointY * pointY))*180/3.1415;
if(pointY>=0)
{
yLineAg = 180-yLineAg;
}
if(pointX<0 && pointY<0)
{
yLineAg += 360;
}
}
void QDiscWidget::mouseReleaseEvent(QMouseEvent * event)
{
}
//绘制圆盘的刻度
void QDiscWidget::draw_disc_scale(QPainter &p)
{
p.save();
QPen pen(QColor(255, 255, 255));
pen.setWidth(0.5);
p.setPen(pen);
for (int i = 0; i < 360; ++i)
{
if ((i % 10) == 0)
{
if ((i % 3) == 0)
{
p.drawLine(0, 0, disc_R, 0);
}
p.drawLine(disc_R - 4, 0, disc_R, 0);
}
else
{
p.drawLine(disc_R - 2, 0, disc_R, 0);
}
p.rotate(1);
}
p.restore();
}
//绘制刻度所对应的字体
void QDiscWidget::draw_disc_text(QPainter &p)
{
p.save();
QString text;
QPen pen(QColor(255, 255, 255));
pen.setWidth(0.5);
p.setPen(pen);
QFont font("Microsoft YaHei", 2);
p.setFont(font);
int pointsize = font.pointSize();
int radius = 100;
float width = pointsize * 3;
float height = pointsize * 2;
for(int i = 0; i < 36; ++i)
{
double y = -(double)radius * 0.97 * qCos(i * M_PI/ 18.0) -1.5;
double x = -(double)radius * 0.97 * qSin(i * M_PI / 18.0) -2.5;
if (i == 0)
{
text = "0";
}
else
{
text = text.sprintf("%d", (360 - 10 * i));
}
p.drawText(QRectF(x, y, width, height), Qt::AlignCenter, text);
}
p.restore();
}
// 画圆内垂直线上半段的刻度以及字体
void QDiscWidget::draw_line_scale(QPainter &p)
{
float h;
QString strText;
QPen pen(QColor(255, 0, 0));
pen.setWidth(0.5);
QFont font("Microsoft YaHei", 3);
p.save();
p.setPen(pen);
p.setFont(font);
for (int i = 1; i < 9; ++i)
{
h = double(-disc_R) / 9.0 * (9-i);
p.drawLine(0, h, 3, h);
p.drawText(QPoint(-5, h), strText.sprintf("%d", (10*i)));
}
p.restore();
}
//画两个内圆
void QDiscWidget::draw_arc(QPainter &p)
{
p.save();
QPen pen(QColor(255, 255, 255));
pen.setWidth(0.5);
p.setPen(pen);
float r = float(disc_R) / 9 * 3;
float r1 = r * 2;
p.drawEllipse(QRect(QPoint(-r, -r), QPoint(r, r)));
p.drawEllipse(QRect(QPoint(-r1, -r1), QPoint(r1, r1)));
p.restore();
}
//给圆盘填充颜色
void QDiscWidget::fill_Gradient_color(QPainter & p)
{
p.save();
QPen pen(QColor(255, 255, 255));
pen.setWidth(0.5);
p.setPen(pen);
//辐射渐变
//QRadialGradient radialgrad(QPointF(0, 0), disc_R);
// QRadialGradient radialgrad(0, 0, disc_R/2, 0, 0);
// radialgrad.setColorAt(0, QColor(0, 0, 100, 150));
// radialgrad.setColorAt(0.5, QColor(170, 0, 200, 150));
// radialgrad.setColorAt(1, QColor(0, 0, 100, 150));
// radialgrad.setSpread(QGradient::ReflectSpread);
//线性渐变
/*QLinearGradient linegrad(QPointF(-90, 10), QPointF(90, 10));
linegrad.setColorAt(0, QColor(0, 0, 100, 150));
linegrad.setColorAt(0.5, QColor(170, 0, 200, 150));
linegrad.setColorAt(1, QColor(0, 0, 100, 150));
linegrad.setSpread(QGradient::RepeatSpread);*/
p.setBrush(QColor(10, 0, 5, 150));
p.drawEllipse(QRect(QPoint(-disc_R, -disc_R), QPoint(disc_R, disc_R)));
p.restore();
}
//绘制可移动的黄线
void QDiscWidget::draw_moveable_yline(QPainter &p)
{
if(yellowLinePoint.isNull())
return;
p.save();
QPen pen(Qt::yellow);
pen.setWidth(0.5);
p.setPen(pen);
p.drawLine(QPoint(0, 0), yellowLinePoint);
p.restore();
}
//绘制黄线移动时,鼠标按下去所显示的线
void QDiscWidget::draw_press_line(QPainter &p)
{
if(pressPoint.isNull() || showRedLine)
return;
p.save();
QPen pen(QColor(85, 170, 255));
pen.setWidth(0.5);
p.setPen(pen);
p.drawLine(QPoint(0, 0), pressPoint);
p.restore();
}
//绘制可移动的红线
void QDiscWidget::draw_moveable_rline(QPainter &p)
{
if(redLinePoint.isNull())
return;
p.save();
QPen pen(Qt::red);
pen.setWidth(0.5);
p.setPen(pen);
p.drawLine(QPoint(0, 0), redLinePoint);
p.restore();
}
void QDiscWidget::resizeEvent(QResizeEvent *event)
{
QWidget::resizeEvent(event);
W = width();
H = height();
}
void QDiscWidget::on_timeout()
{
update();
}
下面的这张图片是本人自己添加的一些功能