VS+Qt应用开发-自定义绘图功能
- 效果展示
- 界面设计
- 代码例程
- 完整代码
- CMyAdjustPoint.h
- CMyAdjustPoint.cpp
- CMyChordItem.h
- CMyChordItem.cpp
- CMyCirItem.h
- CMyCirItem.cpp
- CMyConCirItem.h
- CMyConCirItem.cpp
- CMyEllipseItem.h
- CMyEllipseItem.cpp
- CMyItemBase.h
- CMyItemBase.cpp
- CMyLineItem.h
- CMyLineItem.cpp
- CMyPieItem.h
- CMyPieItem.cpp
- CMyPolygonItem.h
- CMyPolygonItem.cpp
- CMyRect1Item.h
- CMyRect1Item.cpp
- CMyRect2Item.h
- CMyRect2Item.cpp
- CMyRoundRect1Item.h
- CMyRoundRect1Item.cpp
- CMyRoundRect2Item.h
- CMyRoundRect2Item.cpp
- globalVar.h
- globalVar.cpp
- MainWindow.h
- MainWindow.cpp
- MyGraphicsScene.h
- MyGraphicsScene.cpp
- MyGraphicsView.h
- MyGraphicsView.cpp
效果展示
- 动态展示
界面设计
各个控件的对象名设置如下,其中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);
}