.h
#ifndef SHAPEITEM_H
#define SHAPEITEM_H
#include <QGraphicsItem>
#include <QPen>
class ShapeItem : public QGraphicsItem
{
public:
explicit ShapeItem(QGraphicsItem *parent = nullptr);
~ShapeItem();
void setShapeItem(int x1,int y1,int w,int h,int angle);
void setPen(const QPen &pen);
public:
//绘图区域
virtual QRectF boundingRect() const override;
//绘图函数
virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
private:
int m_x1,m_y1,m_w,m_h;
int m_angle;
QPen m_pen;
};
#endif // SHAPEITEM_H
.cpp
#include "ShapeItem.h"
#include <QPainter>
#include<QDebug>
ShapeItem::ShapeItem(QGraphicsItem *parent) : QGraphicsItem(parent)
{
}
ShapeItem::~ShapeItem()
{
}
void ShapeItem::setShapeItem(int x1, int y1, int w, int h,int angle)
{
m_x1=x1;
m_y1=y1;
m_w=w;
m_h=h;
m_angle=angle;
}
void ShapeItem::setPen(const QPen& pen)
{
m_pen=pen;
}
QRectF ShapeItem::boundingRect() const
{
return QRectF(m_x1, m_y1,m_w, m_h);
}
void ShapeItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
// 矩形
QRectF rect(m_x1, m_y1, m_w, m_h);
// 起始角度
int startAngle = 0;
// 跨越度数
double spanAngle = m_angle * 16;
// 反走样
painter->setRenderHint(QPainter::Antialiasing, true);
// 设置画笔颜色、宽度
painter->setPen(m_pen);
// 绘制弧线
painter->drawPie(rect, startAngle, spanAngle);
}
QGraphicsView的使用
.h
#ifndef CANVAS_H
#define CANVAS_H
#include "ShapeItem.h"
#include <QWidget>
#include<QGraphicsView>
#include <QHBoxLayout>
struct Data
{
QString legend;
QString xLeble;
QString yLeble;
QVector<QPointF> points;
};
struct Rgb
{
int r;
int g;
int b;
};
class Canvas : public QWidget
{
Q_OBJECT
public:
explicit Canvas(QWidget *parent = nullptr);
~Canvas();
void draw();
//规范坐标
void setRange(float cormin,float cormax);
//数据源
void addLine(const QString &legend,const QString &xLeble,const QString &yLeble,const QVector<QPointF> &points);
void setTitle(const QString& title);
//跨越度数
void setStepAngle(double angle);
//清空画布中的线
void clearLine();
void test();
private:
//刷新属性
void resetAttribute();
//创建坐标
void createHorizontalAxis();
void createCircleAxis();
//添加字符
void setText(int x,int y,const QString &strText,int fontSize);
//绘制曲线
void curvePlotting();
//颜色
void addAllRgb(int rgbCount);
void creatRgb(int *rgb);
signals:
private:
QGraphicsView *m_pGraphicView;
QHBoxLayout *m_pHBoxLayout;
QGraphicsScene *m_pScene;
QPen *m_pPen;
const float m_pi=3.14159f;
float m_interval;
int m_halfWidth;
int m_halfHeight;
int m_bottomPointX;
int m_angle;
int m_scaleWidth;
double m_stepAngle;
//坐标
int m_cormax,m_cormin,m_cornumber;
//曲线数据
QVector<Data>m_data;
QString m_title;
//rgb
QList<Rgb>m_rgbs;
QList<ShapeItem*>m_listShaps;
// QWidget interface
protected:
void resizeEvent(QResizeEvent* event);
};
#endif // CANVAS_H
.cpp
#include "Canvas.h"
#include"QDebug"
#include <QGraphicsItem>
#include <QResizeEvent>
#include <QTime>
Canvas::Canvas(QWidget *parent) : QWidget(parent)
{
//构建画布
m_pGraphicView=new QGraphicsView;
m_pGraphicView->setRenderHint(QPainter::Antialiasing, true);
m_pGraphicView->setStyleSheet("background-color:rgb(240, 240, 240)");
m_pGraphicView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
m_pGraphicView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
m_pHBoxLayout=new QHBoxLayout;
m_pHBoxLayout->addWidget(m_pGraphicView);
this->setLayout(m_pHBoxLayout);
m_pHBoxLayout->setContentsMargins(0,0,0,0);
//获取一半宽度
m_halfWidth=m_pGraphicView->width()/2;
m_halfHeight=m_pGraphicView->height()/2;
//构建场景
m_pScene = new QGraphicsScene();
m_pGraphicView->setScene(m_pScene);
m_pScene->setSceneRect(-m_halfWidth, -m_halfHeight, m_pGraphicView->width(), m_pGraphicView->height());
m_pGraphicView->setScene(m_pScene);
//画笔
m_pPen=new QPen;
setRange(0,40);
}
Canvas::~Canvas()
{
delete m_pPen;
qDeleteAll(m_listShaps);
m_listShaps.clear();
delete m_pScene;
delete m_pHBoxLayout;
delete m_pGraphicView;
}
void Canvas::draw()
{
qDeleteAll(m_listShaps);
m_listShaps.clear();
createHorizontalAxis();
curvePlotting();
}
void Canvas::resetAttribute()
{
m_halfWidth=m_pGraphicView->width()/2;
m_halfHeight=m_pGraphicView->height()/2;
m_pScene->setSceneRect(-m_halfWidth, -m_halfHeight, m_pGraphicView->width(), m_pGraphicView->height());
}
void Canvas::createHorizontalAxis()
{
m_pScene->clear();
//最右侧点的x坐标
m_bottomPointX=m_halfHeight-40;
m_scaleWidth=m_bottomPointX/20;
m_bottomPointX=m_scaleWidth*20;
setText(0,-m_bottomPointX-35,m_title,15);
m_pPen->setWidth(4);
m_pPen->setColor(QColor(60, 60, 60));
QGraphicsLineItem *lineItem = m_pScene->addLine(QLineF(0,0,m_bottomPointX ,0));
lineItem->setPen(*m_pPen);
createCircleAxis();
float text=m_cormin;
m_interval=(float)((m_cormax-m_cormin)/m_cornumber);
for (int i = 0,x=0; i <= 20; ++i)
{
if(i%5==0)
{
lineItem=m_pScene->addLine(QLineF(x,-8,x,0));
m_pPen->setWidth(4);
m_pPen->setColor(QColor(60,60, 60));
lineItem->setPen(*m_pPen);
setText(x,12, QString("%1").arg(text),10);
text+=m_interval;
}
else
{
lineItem=m_pScene->addLine(QLineF(x,-6,x,0));
m_pPen->setWidth(2);
m_pPen->setColor(QColor(120,120,120));
lineItem->setPen(*m_pPen);
}
x+=m_scaleWidth;
}
}
void Canvas::createCircleAxis()
{
int r=m_bottomPointX;
int interval=m_scaleWidth*5;
ShapeItem *pShapeItem=nullptr;
for (int i = 0; i <=r; i+=interval)
{
m_pPen->setWidth(2);
m_pPen->setColor(QColor(120,120,120));
pShapeItem=new ShapeItem;
m_listShaps.append(pShapeItem);
if(i==r)
{
m_pPen->setWidth(4);
m_pPen->setColor(QColor(60,60,60));
pShapeItem->setPen(*m_pPen);
pShapeItem->setShapeItem(-i,-i,i*2,i*2,m_stepAngle);
m_pScene->addItem(pShapeItem);
}
else
{
pShapeItem->setPen(*m_pPen);
pShapeItem->setShapeItem(-i,-i,i*2,i*2,m_stepAngle);
m_pScene->addItem(pShapeItem);
}
}
int minimumR=interval;
QGraphicsLineItem *lineItem=nullptr;
for (int angle = 0,i=0; angle >= -m_stepAngle; angle-=5,i++)
{
int x1=(int)r*cosf(angle*m_pi/180);
int y1=(int)r*sinf(angle*m_pi/180);
if(i%6!=0)
{
int x2=(int)(r-6)*cosf(angle*m_pi/180);
int y2=(int)(r-6)*sinf(angle*m_pi/180);
lineItem=m_pScene->addLine(QLineF(x1,y1,x2,y2));
m_pPen->setWidth(2);
m_pPen->setColor(QColor(120,120,120));
lineItem->setPen(*m_pPen);
}
else
{
if(!(angle==0||angle==-m_stepAngle))
{
int minX=(int)minimumR*cosf(angle*m_pi/180);
int minY=(int)minimumR*sinf(angle*m_pi/180);
lineItem=m_pScene->addLine(QLineF(x1,y1,minX,minY));
m_pPen->setWidth(2);
m_pPen->setColor(QColor(120,120,120));
lineItem->setPen(*m_pPen);
}
int x2=(int)(r-8)*cosf(angle*m_pi/180);
int y2=(int)(r-8)*sinf(angle*m_pi/180);
lineItem=m_pScene->addLine(QLineF(x1,y1,x2,y2));
m_pPen->setWidth(4);
m_pPen->setColor(QColor(60,60,60));
lineItem->setPen(*m_pPen);
if(-angle>=360){break;}
int textX=(int)(r+15)*cosf(angle*m_pi/180);
int textY=(int)(r+15)*sinf(angle*m_pi/180);
setText(textX,textY,QString::number(-angle),10);
}
}
}
void Canvas::setText(int x,int y,const QString &strText,int fontSize)
{
m_pPen->setWidth(1);
m_pPen->setColor(QColor(60, 60, 60));
QGraphicsSimpleTextItem *textItem=m_pScene->addSimpleText(strText,QFont(QStringLiteral("楷体"),fontSize));
textItem->setPen(*m_pPen);
int width=textItem->boundingRect().width();
int height=textItem->boundingRect().height();
x=x-width/2;
y=y-height/2;
textItem->setPos(x,y);
}
void Canvas::setRange(float cormin, float cormax)
{
int cornumber=4;
float corstep,tmpstep,tmpnumber,temp,extranumber;
if(cormax<=cormin)
return ;
corstep=(cormax-cormin)/cornumber;
if(pow(10,(int)(log(corstep)/log(10)))==corstep)
{
temp = pow(10,(int)(log(corstep)/log(10)));
}
else
{
temp = pow(10,((int)(log(corstep)/log(10))+1));
}
tmpstep = corstep/temp;
//选取规范步长
if(tmpstep>=0&&tmpstep<=0.1)
{
tmpstep = 0.1f;
}
else if(tmpstep>=0.100001&&tmpstep<=0.2)
{
tmpstep = 0.2f;
}
else if(tmpstep>=0.200001&&tmpstep<=0.25)
{
tmpstep = 0.25f;
}
else if(tmpstep>=0.250001&&tmpstep<=0.5)
{
tmpstep = 0.5f;
}
else
{
tmpstep = 1;
}
tmpstep = tmpstep * temp;
//判断最小刻度是否需要+1
if((int)(cormin/tmpstep)!=(cormin/tmpstep))
{
if(cormin<0)
{
cormin = (-1) * ceil(abs(cormin/tmpstep))*tmpstep;
}
else
{
cormin = (int)(abs(cormin/tmpstep))*tmpstep;
}
}
if((int)(cormax/tmpstep)!=(cormax/tmpstep))
{
cormax = (int)(cormax/tmpstep+1)*tmpstep;
}
tmpnumber = (cormax-cormin)/tmpstep;
if(tmpnumber<cornumber)
{
extranumber = cornumber - tmpnumber;
tmpnumber = cornumber;
if((int)extranumber%2 == 0)
{
cormax = cormax + tmpstep*(int)(extranumber/2);
}
else
{
cormax = cormax + tmpstep*(int)(extranumber/2+1);
}
cormin = cormin - tmpstep*(int)(extranumber/2);
}
cornumber = tmpnumber;
m_cormax=cormax;
m_cormin=cormin;
m_cornumber=cornumber;
}
void Canvas::curvePlotting()
{
addAllRgb(m_data.size());
if(m_data.size()==0)return;
int offset=-10;
int lastX=0,lastY=0;
for(int i=0;i<m_data.size();i++)
{
m_pPen->setWidth(2);
m_pPen->setColor(QColor(m_rgbs.at(i).r,m_rgbs.at(i).g,m_rgbs.at(i).b));
QGraphicsLineItem *lineItem = m_pScene->addLine(QLineF(m_bottomPointX+20,-m_halfHeight+30+offset,m_bottomPointX+60,-m_halfHeight+30+offset));
lineItem->setPen(*m_pPen);
//正方形
QGraphicsRectItem *m_rectItem=m_pScene->addRect(QRectF(m_bottomPointX+35,-m_halfHeight+30+offset-5,10,10));
m_rectItem->setPen(*m_pPen);
setText(m_bottomPointX+100,-m_halfHeight+30+offset,m_data.at(i).legend,15);
offset+=20;
bool isFirst=true;
foreach (QPointF point, m_data[i].points)
{
float dataX;float angle;
dataX=point.x();
angle=point.y();
float ratioOffset = m_interval/(m_scaleWidth*5);
dataX=dataX-m_cormin;
int currtX = dataX/ratioOffset;
int x=(int)abs(currtX)*cosf(-(angle)*m_pi/180);
int y=(int)abs(currtX)*sinf(-(angle)*m_pi/180);
if(m_data[i].points.size()!=1&&!isFirst)
{
m_pPen->setWidth(2);
m_pPen->setColor(QColor(m_rgbs.at(i).r,m_rgbs.at(i).g,m_rgbs.at(i).b));
QGraphicsLineItem *lineItem = m_pScene->addLine(QLineF(lastX,lastY,x,y));
lineItem->setPen(*m_pPen);
}
isFirst=false;
lastX=x;
lastY=y;
x=x-m_scaleWidth/2;
y=y-m_scaleWidth/2;
//正方形
QGraphicsRectItem *rect=m_pScene->addRect(QRectF(x,y,m_scaleWidth,m_scaleWidth));
m_pPen->setWidth(2);
m_pPen->setColor(QColor(m_rgbs.at(i).r,m_rgbs.at(i).g,m_rgbs.at(i).b));
rect->setPen(*m_pPen);
}
}
}
void Canvas::addAllRgb(int rgbCount)
{
if(m_rgbs.size()>0)return;
for (int i = 0; i < rgbCount; ++i)
{
int rgb[3];
creatRgb(rgb);
Rgb newRgb;
newRgb.r=rgb[0];
newRgb.g=rgb[1];
newRgb.b=rgb[2];
m_rgbs.append(newRgb);
}
}
void Canvas::creatRgb(int *rgb)
{
for(int i=0;i<=200;i++)
{
for (int j = 0; j < 3; ++j)
{
QTime time;
time= QTime::currentTime();
qsrand(time.msec()*qrand()*qrand());
int randNum = qrand() % 240;
if(j==0)rgb[0]=randNum;
if(j==1)rgb[1]=randNum;
if(j==2)rgb[2]=randNum;
}
if(rgb[0]>200&&rgb[1]>200&&rgb[2]>200)continue;
if(rgb[0]<40&&rgb[1]<40&&rgb[2]<40)continue;
if(m_rgbs.size()==0)return;
for (int k = 0; k < m_rgbs.size(); ++k)
{
if(sqrt(pow(m_rgbs.at(k).r-rgb[0],2)+pow(m_rgbs.at(k).g-rgb[1],2)+pow(m_rgbs.at(k).b-rgb[2],2))<80)
{
break;
}
if(k==m_rgbs.size()-1)return;
}
}
}
void Canvas::setTitle(const QString& title)
{
m_title = title;
}
void Canvas::setStepAngle(double angle)
{
m_stepAngle=angle;
}
void Canvas::clearLine()
{
m_data.clear();
resetAttribute();
draw();
}
void Canvas::addLine(const QString& legend, const QString& xLeble, const QString& yLeble, const QVector<QPointF>& points)
{
Data data;
data.legend=legend;
data.xLeble=xLeble;
data.yLeble=yLeble;
data.points=points;
m_data.append(data);
}
void Canvas::resizeEvent(QResizeEvent* event)
{
resetAttribute();
draw();
event->ignore();
}
void Canvas::test()
{
setRange(100,200);
setTitle(QStringLiteral("xxx曲线"));
setStepAngle(180);
//添加线
for (int var = 0; var < 20; ++var)
{
QVector<QPointF>line;
line.append(QPoint(125,0));
line.append(QPoint(125,30));
line.append(QPoint(110,20));
addLine("R=60m","","",line);
}
//画画
draw();
}
mainwindow.cpp
#include "MainWindow.h"
#include "ui_MainWindow.h"
#include"Canvas.h"
#include<QHBoxLayout>
#include<QDebug>
#include <QVector2D>
#include <QPushButton>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
m_pVBoxLayout=new QVBoxLayout();
m_pCanv=new Canvas;
ui->centralwidget->setLayout(m_pVBoxLayout);
m_pVBoxLayout->setContentsMargins(0,0,0,0);
m_pVBoxLayout->addWidget(m_pCanv);
m_pCanv->test();
m_pBotton =new QPushButton;
m_pBotton->setText("clear");
m_pVBoxLayout->addWidget(m_pBotton);
connect(m_pBotton,&QPushButton::clicked,[this]{
m_pCanv->clearLine();
});
}
MainWindow::~MainWindow()
{
delete m_pVBoxLayout;
delete m_pCanv;
delete m_pBotton;
delete ui;
}
image.png
网友评论