VS+Qt应用开发-自定义绘图功能

效果展示

  • 动态展示

请添加图片描述

界面设计

在这里插入图片描述
各个控件的对象名设置如下,其中graphicsView是Graphics View控件,提升为自定义的MGraphicsView类,关于控件提升请参照我的另一篇博客:
VS+Qt应用开发-控件提升-以Label为例

在这里插入图片描述

代码例程

完整代码

首先贴上完整代码:

CMyAdjustPoint.h

#pragma once

/******************
类功能:锚点类,主要功能如下:
		1.绘制锚点;
		2.接收锚点的鼠标事件,从而对图形进行拖动或改变形状
作者:zh
修改时间:2021-12-24
*******************/


#include <QObject>
#include <QAbstractGraphicsShapeItem>
#include <QPainter>

#include "globalVar.h"

class CMyAdjustPoint : public QObject, public QAbstractGraphicsShapeItem
{
	Q_OBJECT

public:

	enum POINT_TYPE			//锚点的类型,根据图形的类型而异
	{
		Center = 0,			//图形中心,所有的图形
		EdgeStart,			
		EdgeEnd,
		EdgeLU,				
		EdgeRU,
		EdgeL,
		EdgeR,
		EdgeLD,
		EdgeRD,
		Rotate				
	};

	//非Center的锚点是矩形的,指定phi值可让矩形锚点进行选择
	CMyAdjustPoint(QAbstractGraphicsShapeItem *parent, QPointF p,double phi, POINT_TYPE type);

	~CMyAdjustPoint();

	//获取/设置锚点位置
	QPointF getPoint() { return m_point; }				
	void setPoint(QPointF p) { m_point = p; }

	//设置锚点的角度
	void setPhi(double phi);

protected:
	QRectF boundingRect() const;

	void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);	//重绘事件

	void mouseMoveEvent(QGraphicsSceneMouseEvent *event);			//鼠标移动事件,用于常规拖动和修改形状
	void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event);	//鼠标双击事件,用于多边形的增点和减点

private:
	QPointF m_point;		//锚点在父对象的坐标位置,即在图像中的坐标
	POINT_TYPE m_type;		//锚点的类型
	double m_phi;			//锚点的旋转角度
};

CMyAdjustPoint.cpp

#include "CMyAdjustPoint.h"
#include <QCursor>
#include <QGraphicsSceneMouseEvent>

#include "CMyItemBase.h"
#include "CMyLineItem.h"
#include "CMyRect1Item.h"
#include "CMyRect2Item.h"
#include "CMyCirItem.h"
#include "CMyConCirItem.h"
#include "CMyChordItem.h"
#include "CMyPieItem.h"
#include "CMyPolygonItem.h"


CMyAdjustPoint::CMyAdjustPoint(QAbstractGraphicsShapeItem *parent, QPointF p, double phi, POINT_TYPE type)
	:QAbstractGraphicsShapeItem(parent)
	, m_point(p)
	, m_phi(phi)
	, m_type(type)
{
	this->setPos(m_point);			//设置锚点的位置

	this->setFlags(QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsFocusable);

	if (Center == type)
	{
		this->setCursor(Qt::SizeAllCursor);			//中心点十字光标,用于拖动
	}
	else
	{
		this->setCursor(Qt::PointingHandCursor);	//边缘点手型光标,用于调整形状
	}
}

CMyAdjustPoint::~CMyAdjustPoint()
{
}

//设置锚点的角度
void CMyAdjustPoint::setPhi(double phi)
{
	m_phi = phi;
}

QRectF CMyAdjustPoint::boundingRect() const
{
	return QRectF(-g_pointSize / 2.0, -g_pointSize / 2.0, g_pointSize, g_pointSize);
}

//重绘事件
void CMyAdjustPoint::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
	this->setPos(m_point);

	//设置锚点的颜色
	painter->setPen(QPen(Qt::GlobalColor(g_pointColor)));

	//设置锚点填充
	if (g_bIsFillPoint)
	{
		painter->setBrush(QBrush(Qt::GlobalColor(g_pointColor), Qt::SolidPattern));
	}

	painter->rotate(m_phi);		//旋转

	switch (m_type)
	{
	case Center:case Rotate:	//中心锚点和旋转锚点,画成圆形
	{
		painter->drawEllipse(QPointF(0, 0), g_pointSize / 2.0, g_pointSize / 2.0);
		break;
	}
	default:					//其余画为矩形
	{
		painter->drawRect(QRectF(-g_pointSize / 2.0, -g_pointSize / 2.0, g_pointSize, g_pointSize));
		break;
	}
	}
}

//鼠标移动事件
void CMyAdjustPoint::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
	//左键拖动和修改
	if (event->buttons() == Qt::LeftButton)
	{
		qreal dx = event->scenePos().x() - event->lastScenePos().x();
		qreal dy = event->scenePos().y() - event->lastScenePos().y();

		CMyItemBase* item = static_cast<CMyItemBase *>(this->parentItem());		//获取图形
		CMyItemBase::ITEM_TYPE itemType = item->getType();						//获取图形的类型

		item->updateShowPos();		//实时更新坐标

		//平移
		if (Center == m_type)
		{
			item->moveBy(dx, dy);
			this->scene()->update();
		}

#pragma region 调整大小

		//调整大小
		switch (itemType)
		{

#pragma region 直线

		case CMyItemBase::Line:
		{
			m_point = this->mapToParent(event->pos());
			this->setPos(m_point);
			this->scene()->update();

			CMyLineItem *line = dynamic_cast<CMyLineItem *>(item);

			switch (m_type)
			{
			case CMyAdjustPoint::EdgeStart:			//调节起点
			{
				line->setStart(m_point);
				break;
			}
			case CMyAdjustPoint::EdgeEnd:			//调节终点
			{
				line->setEnd(m_point);
				break;
			}
			default:
			{
				break;
			}
			}
			break;
		}
#pragma endregion 直线

#pragma region 矩形

		case CMyItemBase::Rect1:
		{
			m_point = this->mapToParent(event->pos());
			this->setPos(m_point);
			this->scene()->update();

			CMyRect1Item *rect1 = dynamic_cast<CMyRect1Item *>(item);

			switch (m_type)
			{
			case CMyAdjustPoint::EdgeLU:	//调节左上/右上/左下/右下角点
			{
				rect1->setLU(m_point);
				break;
			}
			case CMyAdjustPoint::EdgeRU:
			{
				rect1->setRU(m_point);
				break;
			}
			case CMyAdjustPoint::EdgeLD:
			{
				rect1->setLD(m_point);
				break;
			}
			case CMyAdjustPoint::EdgeRD:
			{
				rect1->setRD(m_point);
				break;
			}
			default:
			{
				break;
			}
			}
			break;
		}

#pragma endregion 矩形

#pragma region 旋转矩形

		case CMyItemBase::Rect2:
		{
			m_point = this->mapToParent(event->pos());
			this->setPos(m_point);
			this->scene()->update();

			CMyRect2Item *rect2 = dynamic_cast<CMyRect2Item *>(item);

			switch (m_type)
			{
			case CMyAdjustPoint::EdgeLU:			//调节左上/右上/左下/右下角点
			{
				rect2->setLU(m_point);
				break;
			}
			case CMyAdjustPoint::EdgeRU:
			{
				rect2->setRU(m_point);
				break;
			}
			case CMyAdjustPoint::EdgeLD:
			{
				rect2->setLD(m_point);
				break;
			}
			case CMyAdjustPoint::EdgeRD:
			{
				rect2->setRD(m_point);
				break;
			}
			case CMyAdjustPoint::Rotate:			//旋转
			{
				rect2->setPhi(m_point);
				break;
			}
			default:
			{
				break;
			}
			}
			break;
		}

#pragma endregion 旋转矩形

#pragma region 圆

		case CMyItemBase::Circle:
		{
			if (m_type == EdgeR)
			{
				m_point = this->mapToParent(event->pos());
				this->setPos(m_point);
				this->scene()->update();

				CMyCirItem *cir = dynamic_cast<CMyCirItem *>(item);
				cir->setR(m_point);
			}
			break;
		}

#pragma endregion 圆

#pragma region 同心圆

		case CMyItemBase::ConCircle:
		{
			m_point = this->mapToParent(event->pos());
			this->setPos(m_point);
			this->scene()->update();

			CMyConCirItem *concir = dynamic_cast<CMyConCirItem *>(item);

			switch (m_type)
			{
			case CMyAdjustPoint::EdgeL:
			{
				concir->setR1(m_point);
				break;
			}
			case CMyAdjustPoint::EdgeR:
			{
				concir->setR2(m_point);
				break;
			}
			default:
				break;
			}
			break;
		}

#pragma endregion 同心圆

#pragma region 弦

		case CMyItemBase::Chord:
		{
			m_point = this->mapToParent(event->pos());
			this->setPos(m_point);
			this->scene()->update();

			CMyChordItem *chord = dynamic_cast<CMyChordItem *>(item);

			if (m_type == EdgeR)
			{
				chord->setR(m_point);
			}
			break;
		}

#pragma endregion 弦

#pragma region 饼

		case CMyItemBase::Pie:
		{
			m_point = this->mapToParent(event->pos());
			this->setPos(m_point);
			this->scene()->update();

			CMyPieItem *pie = dynamic_cast<CMyPieItem *>(item);

			if (m_type == EdgeR)
			{
				pie->setR(m_point);
			}
			break;
		}

#pragma endregion 饼

#pragma region 多边形

		case CMyItemBase::Polygon:
		{
			m_point = this->mapToParent(event->pos());
			this->setPos(m_point);
			this->scene()->update();

			CMyPolygonItem *polygon = dynamic_cast<CMyPolygonItem *>(item);

			if (m_type == EdgeR)
			{
				polygon->setPolygonPoint(QPointF(event->lastScenePos().x(), event->lastScenePos().y()),
					QPointF(event->scenePos().x(), event->scenePos().y()));
			}
			break;
		}

#pragma endregion 多边形

		default:
			break;
		}
#pragma endregion 调整大小

	}
}

//鼠标双击事件,仅用于调整多边形
void CMyAdjustPoint::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
{
	CMyItemBase* item = static_cast<CMyItemBase *>(this->parentItem());
	CMyItemBase::ITEM_TYPE itemType = item->getType();

	m_point = this->mapToParent(event->pos());
	this->setPos(m_point);
	this->scene()->update();

	CMyPolygonItem *polygon = dynamic_cast<CMyPolygonItem *>(item);

	if (event->buttons() == Qt::LeftButton)
	{
		if (CMyItemBase::Polygon == itemType&&EdgeR == m_type)
		{
			polygon->addPolygonPoint(m_point);			//增点
		}
	}
	else if (event->buttons() == Qt::RightButton)
	{
		if (CMyItemBase::Polygon == itemType&&EdgeR == m_type)
		{
			polygon->delPolygonPoint(m_point);			//减点
		}
	}
}

CMyChordItem.h

#pragma once

//弦

#include "CMyItemBase.h"

class CMyChordItem : public CMyItemBase
{
	Q_OBJECT

public:
	CMyChordItem(QPointF center, double r,double phi);
	~CMyChordItem();

	void setR(QPointF p);	//设置半径及角度

protected:
	QRectF boundingRect() const ;
	void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);

private:
	QPointF m_center;		//弦的圆心
	double m_r;				//弦的半径
	double m_phi;			//弦的角度
};

CMyChordItem.cpp

#include "CMyChordItem.h"

CMyChordItem::CMyChordItem(QPointF center, double r, double phi)
	:CMyItemBase(/*center, */ITEM_TYPE::Chord)
{
	m_center = center;
	m_r = r;
	m_phi = phi;

	//添加锚点
	m_adjustPointList.append(new CMyAdjustPoint(this, QPointF(m_center.x() + m_r*cos(m_phi*PI / 180.0), m_center.y() + m_r*sin(m_phi*PI / 180.0)), 0, CMyAdjustPoint::EdgeR));
	m_adjustPointList.append(new CMyAdjustPoint(this, m_center, 0, CMyAdjustPoint::Center));
}

CMyChordItem::~CMyChordItem()
{
}

//设置半径和角度
void CMyChordItem::setR(QPointF p)
{
	m_r = hypot(p.x() - m_center.x(), p.y() - m_center.y());	//勾股公式

	//计算角度
	double theta = atan2((p.y() - m_center.y()), (p.x() - m_center.x()));

	m_phi = theta*180.0 / PI;

	if (m_phi>90)
	{
		m_phi = 180 - m_phi;
	}
}

QRectF CMyChordItem::boundingRect() const
{
	return QRectF(m_center.x() - m_r, m_center.y() - m_r, m_center.x() + m_r, m_center.y() + m_r);
}

//重绘事件
void CMyChordItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
	painter->setRenderHint(QPainter::Antialiasing, true);                   //设置反走样,防锯齿

	//设置画笔
	QPen pen(Qt::GlobalColor(g_shapeColor), g_shapeLineW, Qt::SolidLine);	
	painter->setPen(pen);

	//设置填充
	if (g_bIsFillShape)
	{
		painter->setBrush(QBrush(Qt::GlobalColor(g_shapeColor), Qt::SolidPattern));
	}

	QRectF rect(m_center.x() - m_r, m_center.y() - m_r, m_r * 2, m_r * 2);

	painter->drawChord(rect, -m_phi * 16, (180 + m_phi * 2) * 16);
}

CMyCirItem.h

#pragma once

//圆

#include "CMyItemBase.h"

class CMyCirItem : public CMyItemBase
{
	Q_OBJECT

public:
	CMyCirItem(QPointF center, double r);
	~CMyCirItem();

	void setR(QPointF p);	//设置半径

protected:
	QRectF boundingRect() const;
	void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);

private:
	QPointF m_center;		//圆心
	double m_r;				//半径
};

CMyCirItem.cpp

#include "CMyCirItem.h"

CMyCirItem::CMyCirItem(QPointF center, double r)
	:CMyItemBase(/*center,*/ ITEM_TYPE::Circle)
{
	m_center = center;
	m_r = r;

	//添加锚点
	m_adjustPointList.append(new CMyAdjustPoint(this, QPointF(m_center.x() + m_r, m_center.y()),0, CMyAdjustPoint::EdgeR));
	m_adjustPointList.append(new CMyAdjustPoint(this, m_center, 0, CMyAdjustPoint::Center));

}

CMyCirItem::~CMyCirItem()
{
}

//设置半径
void CMyCirItem::setR(QPointF p)
{
	m_r = hypot(p.x() - m_center.x(), p.y() - m_center.y());
}

QRectF CMyCirItem::boundingRect() const
{
	return QRectF(m_center.x() - m_r, m_center.y() - m_r, m_center.x() + m_r, m_center.y() + m_r);
}

//重绘事件
void CMyCirItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
	painter->setRenderHint(QPainter::Antialiasing, true);                   //设置反走样,防锯齿

	//设置画笔
	QPen pen(Qt::GlobalColor(g_shapeColor), g_shapeLineW, Qt::SolidLine);
	painter->setPen(pen);

	//设置填充
	QBrush brush(Qt::GlobalColor(g_shapeColor), Qt::SolidPattern);
	if (g_bIsFillShape)
	{
		painter->setBrush(brush);
	}

	painter->drawEllipse(m_center, m_r, m_r);
}

CMyConCirItem.h

#pragma once

//同心圆

#include "CMyItemBase.h"

class CMyConCirItem : public CMyItemBase
{
	Q_OBJECT

public:
	CMyConCirItem(QPointF center, double r1,double r2);
	~CMyConCirItem();

	void setR1(QPointF p);	//设置半径
	void setR2(QPointF p);	//设置半径

protected:
	QRectF boundingRect() const;
	void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);

private:
	QPointF m_center;		//圆心
	double m_r1;			//半径1
	double m_r2;			//半径2

};

CMyConCirItem.cpp

#include "CMyConCirItem.h"

CMyConCirItem::CMyConCirItem(QPointF center, double r1, double r2)
	:CMyItemBase(/*center, */ITEM_TYPE::ConCircle)
{
	m_center = center;
	m_r1 = r1;
	m_r2 = r2;

	//添加锚点
	m_adjustPointList.append(new CMyAdjustPoint(this, QPointF(m_center.x() + m_r1, m_center.y()), 0, CMyAdjustPoint::EdgeL));
	m_adjustPointList.append(new CMyAdjustPoint(this, QPointF(m_center.x() + m_r2, m_center.y()), 0, CMyAdjustPoint::EdgeR));
	m_adjustPointList.append(new CMyAdjustPoint(this, m_center, 0, CMyAdjustPoint::Center));
}

CMyConCirItem::~CMyConCirItem()
{
}

//设置半径1
void CMyConCirItem::setR1(QPointF p)
{
	m_r1 = hypot(p.x() - m_center.x(), p.y() - m_center.y());
}

//设置半径2
void CMyConCirItem::setR2(QPointF p)
{
	m_r2= hypot(p.x() - m_center.x(), p.y() - m_center.y());
}

QRectF CMyConCirItem::boundingRect() const
{
	return QRectF(m_center.x() - m_r2, m_center.y() - m_r2, m_center.x() + m_r2, m_center.y() + m_r2);
}

//重绘事件
void CMyConCirItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
	painter->setRenderHint(QPainter::Antialiasing, true);                   //设置反走样,防锯齿
	QPen pen(Qt::GlobalColor(g_shapeColor), g_shapeLineW, Qt::SolidLine);
	
	//设置填充
	if (g_bIsFillShape)
	{
		painter->setBrush(QBrush(Qt::GlobalColor(g_shapeColor), Qt::SolidPattern));
	}
	painter->setPen(pen);

	painter->drawEllipse(m_center, m_r1, m_r1);
	painter->drawEllipse(m_center, m_r2, m_r2);
}

CMyEllipseItem.h

#pragma once

//椭圆,椭圆和矩形很类似,唯一区别是draw函数

#include "CMyRect2Item.h"

class CMyEllipseItem : public CMyRect2Item
{
	Q_OBJECT

public:
	CMyEllipseItem(double x, double y, double w, double h, double phi);
	~CMyEllipseItem();

protected:
	virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;

};

CMyEllipseItem.cpp

#include "CMyEllipseItem.h"


CMyEllipseItem::CMyEllipseItem(double x, double y, double w, double h, double phi)
	:CMyRect2Item(x, y, w, h, phi)
{

}

CMyEllipseItem::~CMyEllipseItem()
{
}

void CMyEllipseItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
	painter->setRenderHint(QPainter::Antialiasing, true);                   //设置反走样,防锯齿

	//设置画笔
	QPen pen(Qt::GlobalColor(g_shapeColor), g_shapeLineW, Qt::SolidLine);
	
	//设置填充
	if (g_bIsFillShape)
	{
		painter->setBrush(QBrush(Qt::GlobalColor(g_shapeColor), Qt::SolidPattern));
	}

	painter->setPen(pen);

	painter->translate(m_x, m_y);
	painter->rotate(m_phi);

	QRect rect(0, 0, m_width, m_height);
	painter->drawEllipse(rect);
}

CMyItemBase.h

#pragma once

//自定义图形的基类

#include <QObject>
#include <QAbstractGraphicsShapeItem>
#include "CMyAdjustPoint.h"
#include <QGraphicsScene>

#define PI 3.141592653

class CMyItemBase : public QObject, public QAbstractGraphicsShapeItem
{
	Q_OBJECT

public:

	enum ITEM_TYPE		//图形的类型
	{
		Line = 0,
		Rect1,
		Rect2,
		Circle,
		ConCircle,
		Polygon,
		RoundRect,
		Chord,
		Pie,
		Ellipse
	};

	CMyItemBase(ITEM_TYPE type);
	~CMyItemBase();

	ITEM_TYPE getType(){ return m_type; }	//获取图形的类型

	void updateShowPos();					//刷新主界面显示的图形锚点坐标

public:
	QList<CMyAdjustPoint *> m_adjustPointList;	//锚点列表

private:
	ITEM_TYPE m_type;						//图形的类型

signals:
	void sg_updateCorners(int type, QList<QPointF>);	//发送锚点坐标

};

CMyItemBase.cpp

#include "CMyItemBase.h"


CMyItemBase::CMyItemBase(ITEM_TYPE type)
	:m_type(type)
{
}

CMyItemBase::~CMyItemBase()
{
}

//刷新显示的坐标
void CMyItemBase::updateShowPos()
{
	QList<QPointF> pList;

	QList<QGraphicsItem *> items = this->scene()->items();
	if (items.size() > 0)
	{
		for (int i = 0; i < m_adjustPointList.size(); i++)
		{
			//转换为图像中的坐标
			QPointF sceneMousePos = this->mapToScene(m_adjustPointList.at(i)->getPoint());
			QPointF itemMousePos = items[items.size() - 1]->mapFromScene(sceneMousePos);
			pList << itemMousePos;
		}
	}

	emit sg_updateCorners(m_type, pList);
}

CMyLineItem.h

#pragma once

//直线图形

#include "CMyItemBase.h"

class CMyLineItem : public CMyItemBase
{
	Q_OBJECT

public:
	CMyLineItem(QPointF pStart, QPointF pEnd);
	~CMyLineItem();

	void setStart(QPointF p);	//设置起点
	void setEnd(QPointF p);		//设置终点

protected:
	QRectF boundingRect() const;
	void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);

private:
	QPointF m_pStart;			//起止点
	QPointF m_pEnd;
};

CMyLineItem.cpp

#include "CMyLineItem.h"


CMyLineItem::CMyLineItem(QPointF pStart, QPointF pEnd)
	:CMyItemBase(ITEM_TYPE::Line)
{
	m_pStart = pStart;
	m_pEnd = pEnd;

	//添加锚点
	m_adjustPointList.append(new CMyAdjustPoint(this, m_pStart, 0, CMyAdjustPoint::EdgeStart));
	m_adjustPointList.append(new CMyAdjustPoint(this, m_pEnd, 0, CMyAdjustPoint::EdgeEnd));
	m_adjustPointList.append(new CMyAdjustPoint(this, (m_pStart + m_pEnd) / 2.0, 0, CMyAdjustPoint::Center));
}

CMyLineItem::~CMyLineItem()
{
}

//设置起点
void CMyLineItem::setStart(QPointF p)
{
	m_pStart = p;
	m_adjustPointList.at(2)->setPoint((m_pStart + m_pEnd) / 2.0);		//重设中心锚点
}

//设置终点
void CMyLineItem::setEnd(QPointF p)
{
	m_pEnd = p;
	m_adjustPointList.at(2)->setPoint((m_pStart + m_pEnd) / 2.0);		//重设中心锚点
}

QRectF CMyLineItem::boundingRect() const
{
	return QRectF(m_pStart.x(), m_pStart.y(), m_pEnd.x() - m_pStart.x(), m_pEnd.y() - m_pStart.y());
}

//重绘事件
void CMyLineItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
	painter->setRenderHint(QPainter::Antialiasing, true);                   //设置反走样,防锯齿
	
	//设置画笔
	QPen pen(Qt::GlobalColor(g_shapeColor), g_shapeLineW, Qt::SolidLine);
	
	painter->setPen(pen);

	QLineF line(m_pStart.x(), m_pStart.y(), m_pEnd.x(), m_pEnd.y());
	painter->drawLine(line);
}

CMyPieItem.h

#pragma once

//饼形

#include "CMyItemBase.h"

class CMyPieItem : public CMyItemBase
{
	Q_OBJECT
public:
	CMyPieItem(QPointF center, double r, double phi);
	~CMyPieItem();

	void setR(QPointF p);	//设置半径及角度

protected:
	QRectF boundingRect() const;
	void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);

private:
	QPointF m_center;		//圆心
	double m_r;				//半径
	double m_phi;			//角度
};

CMyPieItem.cpp

#include "CMyPieItem.h"

CMyPieItem::CMyPieItem(QPointF center, double r, double phi)
	:CMyItemBase(ITEM_TYPE::Pie)
{
	m_center = center;
	m_r = r;
	m_phi = phi;

	//添加锚点
	m_adjustPointList.append(new CMyAdjustPoint(this, QPointF(m_center.x() + m_r*cos(m_phi*PI / 180.0), m_center.y() + m_r*sin(m_phi*PI / 180.0)), 0, CMyAdjustPoint::EdgeR));
	m_adjustPointList.append(new CMyAdjustPoint(this, m_center, 0, CMyAdjustPoint::Center));
}

CMyPieItem::~CMyPieItem()
{
}

//设置半径和角度
void CMyPieItem::setR(QPointF p)
{
	m_r = hypot(p.x() - m_center.x(), p.y() - m_center.y());

	double theta = atan2((p.y() - m_center.y()), (p.x() - m_center.x()));

	m_phi = theta*180.0 / PI;

	if (m_phi>0)
	{
		m_phi = -360 + m_phi;
	}
}

QRectF CMyPieItem::boundingRect() const
{
	return QRectF(m_center.x() - m_r, m_center.y() - m_r, m_center.x() + m_r, m_center.y() + m_r);
}

//重绘事件
void CMyPieItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
	painter->setRenderHint(QPainter::Antialiasing, true);                   //设置反走样,防锯齿
	
	//设置画笔
	QPen pen(Qt::GlobalColor(g_shapeColor), g_shapeLineW, Qt::SolidLine);
	painter->setPen(pen);

	//设置填充
	if (g_bIsFillShape)
	{
		painter->setBrush(QBrush(Qt::GlobalColor(g_shapeColor), Qt::SolidPattern));
	}

	QRectF rect(m_center.x() - m_r, m_center.y() - m_r, m_r * 2, m_r * 2);
	painter->drawPie(rect,0, -m_phi * 16);
}

CMyPolygonItem.h

#pragma once

//多边形

#include "CMyItemBase.h"

class CMyPolygonItem : public CMyItemBase
{
	Q_OBJECT

public:
	CMyPolygonItem();
	~CMyPolygonItem();

	QPointF calcCenter(QList<QPointF> list);			//计算中心
	void calcMaxLength();								//计算极径,作用是确定在boundingRect中刷新的区域
	void setPolygonPoint(QPointF origin, QPointF end);	//移动锚点时刷新重心和极径
	void addPolygonPoint(QPointF origin);				//左键双击锚点时加点
	void delPolygonPoint(QPointF origin);				//右键双击锚点时减点

protected:
	QRectF boundingRect() const;
	void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);

public slots:
	void sls_addPoint(QPointF, QList<QPointF>, bool);	//添加点

private:
	QPointF m_center;			//重心
	double m_length;			//极径
	bool m_isFinished;			//是否绘制完成,右键点击时表示完成
};

CMyPolygonItem.cpp

#include "CMyPolygonItem.h"

CMyPolygonItem::CMyPolygonItem()
	: CMyItemBase(ITEM_TYPE::Polygon)
{
	m_isFinished = false;
}

CMyPolygonItem::~CMyPolygonItem()
{
}

//计算重心
QPointF CMyPolygonItem::calcCenter(QList<QPointF> list)
{
	double x = 0;
	double y = 0;
	for (auto &temp : list)
	{
		x += temp.x();
		y += temp.y();
	}
	x = x / list.size();
	y = y / list.size();

	return QPointF(x, y);
}

//计算极径
void CMyPolygonItem::calcMaxLength()
{
	m_length = 0;

	for (int i = 0; i < m_adjustPointList.size(); i++)
	{
		double dist = hypot(m_adjustPointList.at(i)->x() - m_center.x(), m_adjustPointList.at(i)->y() - m_center.y());

		m_length = dist > m_length ? dist : m_length;
	}
}

//移动锚点时刷新重心和极径
void CMyPolygonItem::setPolygonPoint(QPointF origin, QPointF end)
{
	QList<QPointF> list;

	for (auto &temp : m_adjustPointList)
	{
		if (temp->getPoint() == origin)
		{
			temp->setPoint(end);
		}
		list.append(temp->getPoint());
	}

	m_center = calcCenter(list);
	m_adjustPointList.at(m_adjustPointList.size() - 1)->setPoint(m_center);

	calcMaxLength();
}

//左键双击锚点时加点
void CMyPolygonItem::addPolygonPoint(QPointF origin)
{
	if (m_isFinished)
	{
	QList<QPointF> list;

	QPointF addPoint;
	int index = 0;

	for (int i = 0; i < m_adjustPointList.size();i++)
	{
		if (m_adjustPointList.at(i)->getPoint() == origin)
		{
			index = i;
			if (i == m_adjustPointList.size()-2)
			{
				double x = (m_adjustPointList.at(i)->getPoint().x() + m_adjustPointList.at(0)->getPoint().x()) / 2.0;
				double y = (m_adjustPointList.at(i)->getPoint().y() + m_adjustPointList.at(0)->getPoint().y()) / 2.0;
				addPoint.setX(x);
				addPoint.setY(y);
			}
			else
			{
				double x = (m_adjustPointList.at(i)->getPoint().x() + m_adjustPointList.at(i + 1)->getPoint().x()) / 2.0;
				double y = (m_adjustPointList.at(i)->getPoint().y() + m_adjustPointList.at(i + 1)->getPoint().y()) / 2.0;
				addPoint.setX(x);
				addPoint.setY(y);
			}
		}
		list.append(m_adjustPointList.at(i)->getPoint());
	}

	m_adjustPointList.insert(index + 1, new CMyAdjustPoint(this, addPoint, 0, CMyAdjustPoint::EdgeR));

	m_center = calcCenter(list);
	m_adjustPointList.at(m_adjustPointList.size() - 1)->setPoint(m_center);

	calcMaxLength();
	}
}

//右键锚点时减点
void CMyPolygonItem::delPolygonPoint(QPointF origin)
{
	if (m_isFinished)
	{
		QList<QPointF> list;

		for (int i = 0; i < m_adjustPointList.size(); i++)
		{
			if (m_adjustPointList.at(i)->getPoint() == origin)
			{
				CMyAdjustPoint *p=	m_adjustPointList.takeAt(i);
				delete p;
				p = NULL;
			}
		}

		for (int i = 0; i < m_adjustPointList.size(); i++)
		{
			list.append(m_adjustPointList.at(i)->getPoint());
		}

		m_center = calcCenter(list);
		m_adjustPointList.at(m_adjustPointList.size() - 1)->setPoint(m_center);

		calcMaxLength();
	}
}

QRectF CMyPolygonItem::boundingRect() const
{
	return QRectF(m_center.x() - m_length, m_center.y() - m_length, m_length * 2, m_length * 2);
}

void CMyPolygonItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
	painter->setRenderHint(QPainter::Antialiasing, true);                   //设置反走样,防锯齿
	
	//设置画笔
	QPen pen(Qt::GlobalColor(g_shapeColor), g_shapeLineW, Qt::SolidLine);
	painter->setPen(pen);

	//设置填充
	if (g_bIsFillShape)
	{
		painter->setBrush(QBrush(Qt::GlobalColor(g_shapeColor), Qt::SolidPattern));
	}

	if (m_isFinished)
	{
		QVector<QPointF> pointV;
		for (int i = 0; i < m_adjustPointList.size()-1; i++)
		{
			pointV.append(m_adjustPointList.at(i)->getPoint());
		}
		QPolygonF polygon(pointV);

		painter->drawPolygon(polygon);
	}
	else
	{
		for (int i = 1; i < m_adjustPointList.size(); i++)
		{
			painter->drawLine(m_adjustPointList.at(i - 1)->getPoint(), m_adjustPointList.at(i)->getPoint());
		}
	}
}

//添加点
void CMyPolygonItem::sls_addPoint(QPointF p, QList<QPointF> pointList, bool isFinished)
{ 
	if (!m_isFinished)
	{
		m_center = calcCenter(pointList);
		calcMaxLength();

		if (isFinished)
		{
			m_adjustPointList.append(new CMyAdjustPoint(this, m_center, 0, CMyAdjustPoint::Center));
			m_isFinished = true;
		}
		else
		{
			m_adjustPointList.append(new CMyAdjustPoint(this, p, 0, CMyAdjustPoint::EdgeR));
		}
		this->update();
	}
}

CMyRect1Item.h

#pragma once

//矩形

#include "CMyItemBase.h"

class CMyRect1Item : public CMyItemBase
{
	Q_OBJECT

public:
	CMyRect1Item(double x,double y,double w,double h);
	~CMyRect1Item();

	void setLU(QPointF p);		//设置锚点
	void setRU(QPointF p);		
	void setLD(QPointF p);	
	void setRD(QPointF p);

protected:
	QRectF boundingRect() const;
	void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);

public:
	double m_x, m_y, m_width, m_height;
};

CMyRect1Item.cpp

#include "CMyRect1Item.h"

CMyRect1Item::CMyRect1Item(double x, double y, double w, double h)
	:CMyItemBase(ITEM_TYPE::Rect1)
{
	m_x = x;
	m_y = y;
	m_width = w;
	m_height = h;

	//添加锚点
	m_adjustPointList.append(new CMyAdjustPoint(this, QPointF(x, y), 0, CMyAdjustPoint::EdgeLU));
	m_adjustPointList.append(new CMyAdjustPoint(this, QPointF(x + w, y), 0, CMyAdjustPoint::EdgeRU));
	m_adjustPointList.append(new CMyAdjustPoint(this, QPointF(x, y + h), 0, CMyAdjustPoint::EdgeLD));
	m_adjustPointList.append(new CMyAdjustPoint(this, QPointF(x + w, y + h), 0, CMyAdjustPoint::EdgeRD));

	m_adjustPointList.append(new CMyAdjustPoint(this, QPointF(x + w / 2, y + h / 2), 0, CMyAdjustPoint::Center));
}

CMyRect1Item::~CMyRect1Item()
{
}

//设置角点
void CMyRect1Item::setLU(QPointF p)
{
	m_width = m_x + m_width - p.x();
	m_height = m_y + m_height - p.y();

	m_x = p.x();
	m_y = p.y();

	m_adjustPointList.at(0)->setPoint(QPointF(m_x, m_y));
	m_adjustPointList.at(1)->setPoint(QPointF(m_x + m_width, m_y));
	m_adjustPointList.at(2)->setPoint(QPointF(m_x, m_y + m_height));
	m_adjustPointList.at(3)->setPoint(QPointF(m_x + m_width, m_y + m_height));
	m_adjustPointList.at(4)->setPoint(QPointF(m_x + m_width / 2, m_y + m_height / 2));
}

void CMyRect1Item::setRU(QPointF p)
{
	m_width = p.x() - m_x;
	m_height = m_height + m_y - p.y();

	m_y = p.y();

	m_adjustPointList.at(0)->setPoint(QPointF(m_x, m_y));
	m_adjustPointList.at(1)->setPoint(QPointF(m_x + m_width, m_y));
	m_adjustPointList.at(2)->setPoint(QPointF(m_x, m_y + m_height));
	m_adjustPointList.at(3)->setPoint(QPointF(m_x + m_width, m_y + m_height));
	m_adjustPointList.at(4)->setPoint(QPointF(m_x + m_width / 2, m_y + m_height / 2));
}

void CMyRect1Item::setLD(QPointF p)
{
	m_width = m_x + m_width - p.x();
	m_height = p.y() - m_y;

	m_x = p.x();

	m_adjustPointList.at(0)->setPoint(QPointF(m_x, m_y));
	m_adjustPointList.at(1)->setPoint(QPointF(m_x + m_width, m_y));
	m_adjustPointList.at(2)->setPoint(QPointF(m_x, m_y + m_height));
	m_adjustPointList.at(3)->setPoint(QPointF(m_x + m_width, m_y + m_height));
	m_adjustPointList.at(4)->setPoint(QPointF(m_x + m_width / 2, m_y + m_height / 2));
}

void CMyRect1Item::setRD(QPointF p)
{
	m_width = p.x() - m_x;
	m_height = p.y() - m_y;

	m_adjustPointList.at(0)->setPoint(QPointF(m_x, m_y));
	m_adjustPointList.at(1)->setPoint(QPointF(m_x + m_width, m_y));
	m_adjustPointList.at(2)->setPoint(QPointF(m_x, m_y + m_height));
	m_adjustPointList.at(3)->setPoint(QPointF(m_x + m_width, m_y + m_height));
	m_adjustPointList.at(4)->setPoint(QPointF(m_x + m_width / 2, m_y + m_height / 2));
}

QRectF CMyRect1Item::boundingRect() const
{
	return QRectF(m_x, m_y, m_width, m_height);
}

//重绘事件
void CMyRect1Item::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
	painter->setRenderHint(QPainter::Antialiasing, true);                   //设置反走样,防锯齿
	
	//设置画笔
	QPen pen(Qt::GlobalColor(g_shapeColor), g_shapeLineW, Qt::SolidLine);
	painter->setPen(pen);

	//设置填充
	if (g_bIsFillShape)
	{
		painter->setBrush(QBrush(Qt::GlobalColor(g_shapeColor), Qt::SolidPattern));
	}

	QRect rect(m_x,m_y, m_width, m_height);
	painter->drawRect(rect);
}

CMyRect2Item.h

#pragma once

//旋转矩形

#include "CMyItemBase.h"

class CMyRect2Item : public CMyItemBase
{
	Q_OBJECT

public:
	CMyRect2Item(double x, double y, double w, double h,double phi);
	~CMyRect2Item();

	//根据参数计算各个锚点和中心
	QPointF calcRU();
	QPointF calcLD();
	QPointF calcRD();
	QPointF calcCenter();
	QPointF calcRotate();

	
	void setLU(QPointF p);	
	void setRU(QPointF p);
	void setLD(QPointF p);
	void setRD(QPointF p);
	void setPhi(QPointF p);

protected:
	QRectF boundingRect() const;
	void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);

public:
	double m_x, m_y, m_width, m_height,m_phi;
};

CMyRect2Item.cpp

#include "CMyRect2Item.h"

CMyRect2Item::CMyRect2Item(double x, double y, double w, double h, double phi)
	:CMyItemBase(ITEM_TYPE::Rect2)
{
	m_x = x;
	m_y = y;
	m_width = w;
	m_height = h;
	m_phi = phi;

	//添加锚点
	m_adjustPointList.append(new CMyAdjustPoint(this, QPointF(x, y), phi, CMyAdjustPoint::EdgeLU));
	m_adjustPointList.append(new CMyAdjustPoint(this, calcRU(), phi, CMyAdjustPoint::EdgeRU));
	m_adjustPointList.append(new CMyAdjustPoint(this, calcLD(), phi, CMyAdjustPoint::EdgeLD));
	m_adjustPointList.append(new CMyAdjustPoint(this, calcRD(), phi, CMyAdjustPoint::EdgeRD));

	m_adjustPointList.append(new CMyAdjustPoint(this, calcCenter(), 0, CMyAdjustPoint::Center));
	m_adjustPointList.append(new CMyAdjustPoint(this, calcRotate(), 0, CMyAdjustPoint::Rotate));
}

CMyRect2Item::~CMyRect2Item()
{
}

//设置锚点
void CMyRect2Item::setLU(QPointF p)
{
	double theta = atan2((p.y() - m_y), (p.x() - m_x));
	double delta = theta - m_phi*PI / 180.0;
	double L = hypot(p.x() - m_x, p.y() - m_y);

	m_x = p.x();
	m_y = p.y();

	m_width = m_width - L*cos(delta);
	m_height = m_height - L*sin(delta);

	m_adjustPointList.at(1)->setPoint(calcRU());
	m_adjustPointList.at(2)->setPoint(calcLD());

	m_adjustPointList.at(4)->setPoint(calcCenter());
	m_adjustPointList.at(5)->setPoint(calcRotate());
	update();
}

void CMyRect2Item::setRU(QPointF p)
{
	double theta = atan2((p.y() - calcRU().y()), (p.x() - calcRU().x()));
	double delta = theta - m_phi*PI / 180.0;
	double L = hypot(p.x() - calcRU().x(), p.y() - calcRU().y());

	m_width = m_width + L*cos(delta);
	m_height = m_height - L*sin(delta);

	m_x = m_x + L*sin(delta)*sin(-m_phi*PI / 180.0);
	m_y = m_y + L*sin(delta)*cos(-m_phi*PI / 180.0);

	m_adjustPointList.at(0)->setPoint(QPointF(m_x, m_y));
	m_adjustPointList.at(3)->setPoint(calcRD());

	m_adjustPointList.at(4)->setPoint(calcCenter());
	m_adjustPointList.at(5)->setPoint(calcRotate());
	update();
}

void CMyRect2Item::setLD(QPointF p)
{
	double theta = atan2((p.y() - calcLD().y()), (p.x() - calcLD().x()));
	double delta = theta - m_phi*PI / 180.0;
	double L = hypot(p.x() - calcLD().x(), p.y() - calcLD().y());

	m_width = m_width - L*cos(delta);
	m_height = m_height + L*sin(delta);

	m_x = m_x + L*cos(delta)*cos(-m_phi*PI / 180.0);
	m_y = m_y - L*cos(delta)*sin(-m_phi*PI / 180.0);

	m_adjustPointList.at(0)->setPoint(QPointF(m_x, m_y));
	m_adjustPointList.at(3)->setPoint(calcRD());

	m_adjustPointList.at(4)->setPoint(calcCenter());
	m_adjustPointList.at(5)->setPoint(calcRotate());
	update();
}

void CMyRect2Item::setRD(QPointF p)
{
	double theta = atan2((p.y() - calcRD().y()), (p.x() - calcRD().x()));
	double delta = theta - m_phi*PI / 180.0;
	double L = hypot(p.x() - calcRD().x(), p.y() - calcRD().y());

	m_width = m_width + L*cos(delta);
	m_height = m_height + L*sin(delta);

	m_adjustPointList.at(1)->setPoint(calcRU());
	m_adjustPointList.at(2)->setPoint(calcLD());

	m_adjustPointList.at(4)->setPoint(calcCenter());
	m_adjustPointList.at(5)->setPoint(calcRotate());
	update();
}

void CMyRect2Item::setPhi(QPointF p)
{
	QPointF center = calcCenter();

	double theta = atan2((p.y() - calcCenter().y()), (p.x() - calcCenter().x()));

	m_phi = theta*180.0 / PI;

	m_x = center.x() - (m_height*sin(-m_phi*PI / 180.0) + m_width*cos(-m_phi*PI / 180.0)) / 2.0;
	m_y = center.y() - (m_height*cos(-m_phi*PI / 180.0) - m_width*sin(-m_phi*PI / 180.0)) / 2.0;


	m_adjustPointList.at(0)->setPoint(QPointF(m_x, m_y));

	m_adjustPointList.at(1)->setPoint(calcRU());
	m_adjustPointList.at(2)->setPoint(calcLD());
	m_adjustPointList.at(3)->setPoint(calcRD());

	m_adjustPointList.at(0)->setPhi(m_phi);
	m_adjustPointList.at(1)->setPhi(m_phi);
	m_adjustPointList.at(2)->setPhi(m_phi);
	m_adjustPointList.at(3)->setPhi(m_phi);

	update();
}

QRectF CMyRect2Item::boundingRect() const
{
	return QRectF(m_x, m_y, m_width, m_height);
}

//重绘事件
void CMyRect2Item::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
	painter->setRenderHint(QPainter::Antialiasing, true);                   //设置反走样,防锯齿

	//设置画笔
	QPen pen(Qt::GlobalColor(g_shapeColor), g_shapeLineW, Qt::SolidLine);
	painter->setPen(pen);

	//设置填充
	if (g_bIsFillShape)
	{
		painter->setBrush(QBrush(Qt::GlobalColor(g_shapeColor), Qt::SolidPattern));
	}

	painter->translate(m_x, m_y);
	painter->rotate(m_phi);

	QRect rect(0, 0, m_width, m_height);
	painter->drawRect(rect);
}


//根据参数计算各个锚点和中心
QPointF CMyRect2Item::calcRU()
{
	return QPointF(m_x + m_width*cos(-m_phi*PI / 180.0), m_y - m_width*sin(-m_phi*PI / 180.0));
}

QPointF CMyRect2Item::calcLD()
{
	return QPointF(m_x + m_height*sin(-m_phi*PI / 180.0), m_y + m_height*cos(-m_phi*PI / 180.0));
}

QPointF CMyRect2Item::calcRD()
{
	return QPointF(m_x + m_height*sin(-m_phi*PI / 180.0) + m_width*cos(-m_phi*PI / 180.0), m_y + m_height*cos(-m_phi*PI / 180.0) - m_width*sin(-m_phi*PI / 180.0));
}

QPointF CMyRect2Item::calcCenter()
{
	return QPointF(m_x + (m_height*sin(-m_phi*PI / 180.0) + m_width*cos(-m_phi*PI / 180.0)) / 2.0, m_y + (m_height*cos(-m_phi*PI / 180.0) - m_width*sin(-m_phi*PI / 180.0)) / 2.0);
}

QPointF CMyRect2Item::calcRotate()
{
	return QPointF(m_x + m_width*cos(-m_phi*PI / 180.0) + m_height*sin(-m_phi*PI / 180.0) / 2.0 + 10 * cos(-m_phi*PI / 180.0), m_y - m_width*sin(-m_phi*PI / 180.0) + m_height*cos(-m_phi*PI / 180.0) / 2.0 - 10 * sin(-m_phi*PI / 180.0));
}

CMyRoundRect1Item.h

#pragma once

//圆角矩形1

#include "CMyRect1Item.h"

class CMyRoundRect1Item : public CMyRect1Item
{
	Q_OBJECT

public:
	CMyRoundRect1Item(double x, double y, double w, double h);
	~CMyRoundRect1Item();

protected:
	void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
};

CMyRoundRect1Item.cpp

#include "CMyRoundRect1Item.h"

CMyRoundRect1Item::CMyRoundRect1Item(double x, double y, double w, double h)
	: CMyRect1Item(x, y, w, h)
{
}

CMyRoundRect1Item::~CMyRoundRect1Item()
{
}


//重绘事件
void CMyRoundRect1Item::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
	painter->setRenderHint(QPainter::Antialiasing, true);                   //设置反走样,防锯齿
	
	//设置画笔
	QPen pen(Qt::GlobalColor(g_shapeColor), g_shapeLineW, Qt::SolidLine);
	painter->setPen(pen);

	//设置填充
	if (g_bIsFillShape)
	{
		painter->setBrush(QBrush(Qt::GlobalColor(g_shapeColor), Qt::SolidPattern));
	}

	QRect rect(m_x, m_y, m_width, m_height);
	painter->drawRoundedRect(rect, m_height / 2.0, m_height / 2.0);
}

CMyRoundRect2Item.h

#pragma once

//旋转圆角矩形

#include "CMyRect2Item.h"

class CMyRoundRect2Item : public CMyRect2Item
{
	Q_OBJECT

public:
	CMyRoundRect2Item(double x, double y, double w, double h, double phi);
	~CMyRoundRect2Item();

protected:
	void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
};

CMyRoundRect2Item.cpp

#include "CMyRoundRect2Item.h"

CMyRoundRect2Item::CMyRoundRect2Item(double x, double y, double w, double h, double phi)
	:CMyRect2Item(x, y, w, h, phi)
{
}

CMyRoundRect2Item::~CMyRoundRect2Item()
{
}

void CMyRoundRect2Item::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
	painter->setRenderHint(QPainter::Antialiasing, true);                   //设置反走样,防锯齿

	//设置画笔
	QPen pen(Qt::GlobalColor(g_shapeColor), g_shapeLineW, Qt::SolidLine);
	painter->setPen(pen);

	//设置填充
	if (g_bIsFillShape)
	{
		painter->setBrush(QBrush(Qt::GlobalColor(g_shapeColor), Qt::SolidPattern));
	}

	painter->translate(m_x, m_y);
	painter->rotate(m_phi);

	QRect rect(0, 0, m_width, m_height);
	painter->drawRoundedRect(rect, m_height / 2.0, m_height / 2.0);
}

globalVar.h


#pragma execution_character_set("utf-8")

extern int g_shapeColor;
extern int g_shapeLineW;

extern int g_pointColor;
extern int g_pointSize;

extern bool g_bIsFillShape;
extern bool g_bIsFillPoint;

globalVar.cpp

#include "globalVar.h"

int g_shapeColor = 0;				//图形颜色
int g_shapeLineW = 0;				//图形宽度

int g_pointColor = 0;				//锚点颜色
int g_pointSize = 0;				//锚点尺寸

bool g_bIsFillShape = false;		//是否填充形状
bool g_bIsFillPoint = false;		//是否填充锚点

MainWindow.h

#pragma once

#include <QtWidgets/QMainWindow>
#include "ui_MainWindow.h"
#include <QGraphicsScene>
#include <QGraphicsItem>

#include "MyGraphicsScene.h"
#include "CMyLineItem.h"
#include "CMyRect1Item.h"
#include "CMyRect2Item.h"
#include "CMyCirItem.h"
#include "CMyConCirItem.h"
#include "CMyRoundRect1Item.h"
#include "CMyRoundRect2Item.h"
#include "CMyChordItem.h"
#include "CMyPieItem.h"
#include "CMyEllipseItem.h"
#include "CMyPolygonItem.h"

class MainWindow : public QMainWindow
{
	Q_OBJECT

public:
	MainWindow(QWidget *parent = Q_NULLPTR);
	~MainWindow();

	void frmInit();							//界面初始化
	void paramInit();						//参数初始化

private slots:	
	void on_btn_loadImg_clicked();			//加载图片
	void on_btn_drawLine_clicked();			//绘制直线
	void on_btn_drawRect1_clicked();		//绘制正矩形
	void on_btn_drawRect2_clicked();		//绘制旋转矩形
	void on_btn_drawCir_clicked();			//绘制圆形
	void on_btn_drawConCir_clicked();		//绘制同心圆
	void on_btn_drawPolygon_clicked();		//绘制多边形
	
	void on_btn_drawRoundRect1_clicked();	//绘制圆角矩形1
	void on_btn_drawRoundRect2_clicked();	//绘制圆角矩形2

	void on_btn_drawChord_clicked();		//绘制弦
	void on_btn_drawPie_clicked();			//绘制饼

	void on_btn_drawEllipse_clicked();		//绘制椭圆

	void on_cbBox_shapeColor_currentIndexChanged(int);		//改变形状颜色
	void on_cbBox_pointColor_currentIndexChanged(int);		//改变锚点颜色
	void on_cbBox_shapeLineW_currentIndexChanged(int);		//改变形状线宽
	void on_cbBox_pointSize_currentIndexChanged(int);		//改变锚点大小

	void on_ckBox_fillShape_stateChanged(int);				//形状填充
	void on_ckBox_fillPoint_stateChanged(int);				//锚点填充

	void on_btn_clear_clicked();							//清空

	void sls_updateShowPos(int, QList<QPointF>);			//显示图形的锚点坐标

private:
	QGraphicsPixmapItem *m_imgItem;
	MyGraphicsScene *m_graphicsScene;

	Ui::MainWindowClass ui;
};

MainWindow.cpp

#include "MainWindow.h"
#include <QDir>

MainWindow::MainWindow(QWidget *parent)
	: QMainWindow(parent)
	, m_graphicsScene(NULL)
{
	ui.setupUi(this);

	frmInit();
	paramInit();
}

MainWindow::~MainWindow()
{
	if (m_imgItem!=NULL)
	{
		delete m_imgItem;
		m_imgItem = NULL;
	}

	delete m_graphicsScene;
	m_graphicsScene = NULL;
}

void MainWindow::frmInit()
{
	QMap<QString, int> shapeColorMap;

	shapeColorMap.insert("白色", Qt::white);
	shapeColorMap.insert("黑色", Qt::black);
	shapeColorMap.insert("红色", Qt::red);
	shapeColorMap.insert("绿色", Qt::green);
	shapeColorMap.insert("蓝色", Qt::blue);
	shapeColorMap.insert("黄色", Qt::yellow);

	QMap<QString, int>::Iterator it = shapeColorMap.begin();
	while (it != shapeColorMap.end())
	{
		QPixmap pix(20, 20);
		pix.fill(Qt::GlobalColor(it.value()));
		ui.cbBox_shapeColor->addItem(QIcon(pix), it.key(), it.value());		//形状颜色
		ui.cbBox_pointColor->addItem(QIcon(pix), it.key(), it.value());		//锚点颜色
		it++;
	}

	ui.cbBox_shapeColor->setCurrentIndex(1);
	ui.cbBox_pointColor->setCurrentIndex(2);

	ui.cbBox_shapeLineW->setCurrentIndex(1);
	ui.cbBox_pointSize->setCurrentIndex(2);
}

//参数初始化
void MainWindow::paramInit()
{
	m_imgItem = new QGraphicsPixmapItem;				//图像元素
	m_graphicsScene = new MyGraphicsScene;				//自定义场景
	m_graphicsScene->addItem(m_imgItem);
	m_graphicsScene->setBackgroundBrush(Qt::black);

	ui.graphicsView->setScene(m_graphicsScene);

	//鼠标移动时,显示坐标
	connect(ui.graphicsView, &MyGraphicsView::updatePos, this, [=](QPointF pos)
	{
		QString str = QString("coordinate: ") + "(" + QString::number(int(pos.x())) + "," + QString::number(int(pos.y())) + ")";
		ui.label_pos->setText(str);
	});
}

//加载图片
void MainWindow::on_btn_loadImg_clicked()
{
	QList<QGraphicsItem *> items=m_graphicsScene->items();

	if (items.size() == 0)
	{
		m_imgItem = new QGraphicsPixmapItem;

		m_graphicsScene->addItem(m_imgItem);
	}

	QImage img("./image.bmp");
	m_imgItem->setPixmap(QPixmap::fromImage(img));
	ui.graphicsView->fitInView(m_imgItem, Qt::KeepAspectRatio);
}

//绘制直线
void MainWindow::on_btn_drawLine_clicked()
{
	CMyLineItem *line = new CMyLineItem(QPointF(20, 20), QPointF(100, 100));
	m_graphicsScene->addItem(line);

	connect(line, SIGNAL(sg_updateCorners(int, QList<QPointF>)), this, SLOT(sls_updateShowPos(int, QList<QPointF>)));

	m_graphicsScene->update();
}

//绘制正矩形
void MainWindow::on_btn_drawRect1_clicked()
{
	CMyRect1Item *rect = new CMyRect1Item(20, 20, 100, 100);
	m_graphicsScene->addItem(rect);

	connect(rect, SIGNAL(sg_updateCorners(int, QList<QPointF>)), this, SLOT(sls_updateShowPos(int, QList<QPointF>)));

	m_graphicsScene->update();
}

//绘制旋转矩形
void MainWindow::on_btn_drawRect2_clicked()
{
	CMyRect2Item *rect2 = new CMyRect2Item(20, 20, 100, 50, -30);
	m_graphicsScene->addItem(rect2);

	connect(rect2, SIGNAL(sg_updateCorners(int, QList<QPointF>)), this, SLOT(sls_updateShowPos(int, QList<QPointF>)));

	m_graphicsScene->update();
}

//绘制圆形
void MainWindow::on_btn_drawCir_clicked()
{
	CMyCirItem *cir = new CMyCirItem(QPointF(20, 20), 100);
	m_graphicsScene->addItem(cir);

	connect(cir, SIGNAL(sg_updateCorners(int, QList<QPointF>)), this, SLOT(sls_updateShowPos(int, QList<QPointF>)));

	m_graphicsScene->update();
}

//绘制同心圆
void MainWindow::on_btn_drawConCir_clicked()
{
	CMyConCirItem *concir = new CMyConCirItem(QPointF(20, 20), 100, 150);
	m_graphicsScene->addItem(concir);

	connect(concir, SIGNAL(sg_updateCorners(int, QList<QPointF>)), this, SLOT(sls_updateShowPos(int, QList<QPointF>)));

	m_graphicsScene->update();
}

//绘制多边形
void MainWindow::on_btn_drawPolygon_clicked()
{
	m_graphicsScene->startDrawPolygon();
	CMyPolygonItem *polygon = new CMyPolygonItem();
	m_graphicsScene->addItem(polygon);

	connect(polygon, SIGNAL(sg_updateCorners(int, QList<QPointF>)), this, SLOT(sls_updateShowPos(int, QList<QPointF>)));

	m_graphicsScene->update();

	connect(m_graphicsScene, SIGNAL(sg_updatePoint(QPointF, QList<QPointF>, bool)), polygon, SLOT(sls_addPoint(QPointF, QList<QPointF>, bool)));
}

//绘制圆角矩形1
void MainWindow::on_btn_drawRoundRect1_clicked()
{
	CMyRoundRect1Item *roundRect1 = new CMyRoundRect1Item(20, 20, 100, 100);
	m_graphicsScene->addItem(roundRect1);

	connect(roundRect1, SIGNAL(sg_updateCorners(int, QList<QPointF>)), this, SLOT(sls_updateShowPos(int, QList<QPointF>)));

	m_graphicsScene->update();
}

//绘制圆角矩形2
void MainWindow::on_btn_drawRoundRect2_clicked()
{
	CMyRoundRect2Item *roundRect2 = new CMyRoundRect2Item(20, 20, 100, 50, -30);
	m_graphicsScene->addItem(roundRect2);

	connect(roundRect2, SIGNAL(sg_updateCorners(int, QList<QPointF>)), this, SLOT(sls_updateShowPos(int, QList<QPointF>)));

	m_graphicsScene->update();
}

//绘制弦
void MainWindow::on_btn_drawChord_clicked()
{
	CMyChordItem *chord = new CMyChordItem(QPointF(20, 20), 100, -30);
	m_graphicsScene->addItem(chord);

	connect(chord, SIGNAL(sg_updateCorners(int, QList<QPointF>)), this, SLOT(sls_updateShowPos(int, QList<QPointF>)));

	m_graphicsScene->update();
}

//绘制饼
void MainWindow::on_btn_drawPie_clicked()
{
	CMyPieItem *pie = new CMyPieItem(QPointF(20, 20), 100, -30);
	m_graphicsScene->addItem(pie);

	connect(pie, SIGNAL(sg_updateCorners(int, QList<QPointF>)), this, SLOT(sls_updateShowPos(int, QList<QPointF>)));

	m_graphicsScene->update();
}

//绘制椭圆
void MainWindow::on_btn_drawEllipse_clicked()
{
	CMyEllipseItem *ellipse = new CMyEllipseItem(20, 20, 100, 50, -30);
	m_graphicsScene->addItem(ellipse);

	connect(ellipse, SIGNAL(sg_updateCorners(int, QList<QPointF>)), this, SLOT(sls_updateShowPos(int, QList<QPointF>)));

	m_graphicsScene->update();
}

//改变形状颜色
void MainWindow::on_cbBox_shapeColor_currentIndexChanged(int index)
{
	g_shapeColor = ui.cbBox_shapeColor->itemData(index).toInt();

	if (m_graphicsScene != NULL)
	{
		m_graphicsScene->update();
	}
}

//改变锚点颜色
void MainWindow::on_cbBox_pointColor_currentIndexChanged(int index)
{
	g_pointColor = ui.cbBox_pointColor->itemData(index).toInt();

	if (m_graphicsScene != NULL)
	{
		m_graphicsScene->update();
	}
}

//改变形状线宽
void MainWindow::on_cbBox_shapeLineW_currentIndexChanged(int)
{
	g_shapeLineW = ui.cbBox_shapeLineW->currentText().toInt();

	if (m_graphicsScene != NULL)
	{
		m_graphicsScene->update();
	}
}

//改变锚点大小
void MainWindow::on_cbBox_pointSize_currentIndexChanged(int)
{
	g_pointSize = ui.cbBox_pointSize->currentText().toInt();

	if (m_graphicsScene != NULL)
	{
		m_graphicsScene->update();
	}
}

//形状填充
void MainWindow::on_ckBox_fillShape_stateChanged(int flg)
{
	g_bIsFillShape = flg;
	if (m_graphicsScene != NULL)
	{
		m_graphicsScene->update();
	}
}

//锚点填充
void MainWindow::on_ckBox_fillPoint_stateChanged(int flg)
{
	g_bIsFillPoint = flg;
	if (m_graphicsScene != NULL)
	{
		m_graphicsScene->update();
	}
}

//清空
void MainWindow::on_btn_clear_clicked()
{
	m_graphicsScene->clear();
}

void MainWindow::sls_updateShowPos(int type, QList<QPointF> pList)
{
	ui.textEdit->clear();

	for (int i = 0; i < pList.size(); i++)
	{
		ui.textEdit->append(QString("(x%1:%2,y%3:%4)").arg(i + 1).arg(int(pList[i].x())).arg(i + 1).arg(int(pList[i].y())));
	}
}

MyGraphicsScene.h

#pragma once

#include <QGraphicsScene>

class MyGraphicsScene : public QGraphicsScene
{
	Q_OBJECT

public:
	MyGraphicsScene(QObject *parent=NULL);
	~MyGraphicsScene();

	void startDrawPolygon();								//开始绘制多边形

	void mousePressEvent(QGraphicsSceneMouseEvent *event);

signals:
	void sg_updatePoint(QPointF p, QList<QPointF> list, bool isCenter);
	void sg_finishDrawPolygon();

public:
	QList<QPointF> m_list;

	bool m_bIsDrawingPolygon;
};

MyGraphicsScene.cpp

#include "MyGraphicsScene.h"
#include <QGraphicsSceneMouseEvent>

MyGraphicsScene::MyGraphicsScene(QObject *parent)
	: QGraphicsScene(parent)
{
	m_bIsDrawingPolygon = false;
}

MyGraphicsScene::~MyGraphicsScene()
{
}

//开始绘制多边形
void MyGraphicsScene::startDrawPolygon()
{
	m_bIsDrawingPolygon = true;
}

void MyGraphicsScene::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
	if (m_bIsDrawingPolygon)
	{
		QPointF p(event->scenePos().x(), event->scenePos().y());

		switch (event->buttons())
		{
		case Qt::LeftButton:
		{
			m_list.push_back(p);
			emit sg_updatePoint(p, m_list, false);

			break;
		} 
		case Qt::RightButton:
		{
			if (m_list.size() >= 3)
			{
				emit sg_updatePoint(p, m_list, true);
				emit sg_finishDrawPolygon();
				m_bIsDrawingPolygon = false;
				m_list.clear();
			}
			break;
		} 
		default:
			break;
		}
	}
	else
	{
		QGraphicsScene::mousePressEvent(event);
	}
}

MyGraphicsView.h

#pragma once

#include <QGraphicsView>

class MyGraphicsView : public QGraphicsView
{
	Q_OBJECT

public:
	MyGraphicsView(QWidget *parent = NULL);
	~MyGraphicsView();

	void mousePressEvent(QMouseEvent *ev);			//鼠标按下事件
	void mouseReleaseEvent(QMouseEvent *ev);		//鼠标松开事件
	void mouseMoveEvent(QMouseEvent *ev);			//鼠标移动事件

	void wheelEvent(QWheelEvent *ev);				//缩放函数

	void translate(QPointF);						//平移函数

private:
	bool m_bIsMove;				//是否进行平移
	QPoint m_pressedPos;		//平移时鼠标点下的位置
	double m_zoomDelta;			//缩放因子

signals:
	void updatePos(QPointF);

};

MyGraphicsView.cpp

#include "MyGraphicsView.h"
#include <QMouseEvent>
#include <QGraphicsItem>

MyGraphicsView::MyGraphicsView(QWidget *parent)
	: QGraphicsView(parent)
{
	m_bIsMove = false;
	m_zoomDelta = 0.1;

	setSceneRect(INT_MIN / 2, INT_MIN / 2, INT_MAX, INT_MAX);
	setDragMode(NoDrag);

	// 去掉滚动条
	setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
	setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);

	setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
	setResizeAnchor(QGraphicsView::AnchorUnderMouse);
}

MyGraphicsView::~MyGraphicsView()
{
}

//鼠标按下事件
void MyGraphicsView::mousePressEvent(QMouseEvent *ev)
{
	//右键平移
	if (ev->button()==Qt::RightButton)
	{
		m_bIsMove = true;
		m_pressedPos = ev->pos();
	}

	QGraphicsView::mousePressEvent(ev);
}

//鼠标松开事件
void MyGraphicsView::mouseReleaseEvent(QMouseEvent *ev)
{
	//右键平移
	if (ev->button() == Qt::RightButton)
	{
		m_bIsMove = false;
	}

	QGraphicsView::mouseReleaseEvent(ev);
}

//鼠标移动事件
void MyGraphicsView::mouseMoveEvent(QMouseEvent *ev)
{
	if (m_bIsMove)
	{
		QPointF mouseDelta =ev->pos() - m_pressedPos;
		translate(mouseDelta);
	}

	m_pressedPos = ev->pos();

	QList<QGraphicsItem *> item = this->scene()->items(ev->pos());
	if (item.size()>0)
	{
		QPointF sceneMousePos = this->mapToScene(ev->pos());
		QPointF itemMousePos = item[item.size()-1]->mapFromScene(sceneMousePos);
		emit updatePos(itemMousePos);
	}
	else 
	{
		QPointF p(0, 0);
		emit updatePos(p);
	}

	QGraphicsView::mouseMoveEvent(ev);
}

//缩放函数
void MyGraphicsView::wheelEvent(QWheelEvent *ev)
{
	// 滚轮的滚动量
	QPoint scrollAmount = ev->angleDelta();

	// 正值表示滚轮远离使用者(放大),负值表示朝向使用者(缩小)
	double zoomFactor = 0;
	zoomFactor = scrollAmount.y() > 0 ? (1 + m_zoomDelta) : (1 - m_zoomDelta);

	// 防止太小或过大
	qreal factor = transform().scale(zoomFactor, zoomFactor).mapRect(QRectF(0, 0, 1, 1)).width();
	if (factor < 0.07 || factor > 100)
	{
		return;
	}

	scale(zoomFactor, zoomFactor);
}


//平移函数
void MyGraphicsView::translate(QPointF delta)
{
	// view 根据鼠标下的点做为锚点来定位 scene
	setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
	QPoint newCenter(viewport()->rect().width() / 2 - delta.x(), viewport()->rect().height() / 2 - delta.y());
	centerOn(mapToScene(newCenter));

	// scene 在 view 的中心点做为锚点
	setTransformationAnchor(QGraphicsView::AnchorViewCenter);
}

  • 8
    点赞
  • 47
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值