SVG编辑器

week05–SVG编辑器

在Visual Studio 2019下使用QT环境编写SVG编辑器,要求编辑器可以根据鼠标移动绘出各种基础图形(直线、矩形、圆形、五边形、六边形、五角星、文本、铅笔自由线)以及可以设置各种图形的填充颜色和边框颜色,并且在鼠标选中时可以进行拖拽移动、边框伸缩、顶点拖拽转动,画布及其图形缩放,以及对各种图形的上下层进行设置,同时对于画布可以设置颜色。并且对与svg文件保存方面,可以将画布及其上面的图形样式保存为SVG,以及打开通用SVG文件,并且可以将SVG文件导出为PNG文件鼠标右键菜单栏可以删除图形撤回上一步所画图形。

程序测试说明

程序点击左侧图形可以进行图形的绘画,
点击鼠标图标:
在这里插入图片描述可以对图形进行移动和拖拽。以及选中图形进行颜色和边框的填充。
点击放大镜图标:
在这里插入图片描述后滚动滑轮,可以对画布进行放缩操作。
点击其他各种图形包括文本,可以画出对应的需要的图形。

测试内存泄漏:

经测试,开始是存在内存泄露的,在一顿查找后,找到是在GlobalData类中的静态成员变量中产生了内存泄漏,C++在程序析构时,静态成员变量和静态成员函数是系统自动析构的,但是由于多重调用,导致该类的静态成员变量未完全析构,之后我选择写一个静态成员函数,在主函数析构的时候调用静态成员函数对该静态成员变量进行析构,果真未再出现内存泄漏。所以程序现在已经不存在内存泄漏。

程序具体实现思路:

由于svg编辑器类似于画图软件,因此在实现的时候,对于鼠标点击位置以及拖拽位置和鼠标释放位置要求都不一样,因此本次程序的重点是重写鼠标点击事件鼠标移动事件鼠标释放事件,同时由于各种图形的绘画需要一个对象统一管理,因此使用工厂模式设置ShapeFactory类对各种不同的图形、自由线、Text文本进行管理,同时也大大增加了程序的可扩展性,由于画板类的各种操作需要跟其他类,例如属性类,工具栏类,菜单栏类进行交互,因此使用单例模式设置一个统一的数据类(GlobalData)类对各种属性以及操作进行保存,调用和设置。增加代码统一管理的有序性,以及健壮性。

程序文件结构:

在这里插入图片描述
各种文件主要分为图形基类、具体图形类、画布类、图形工厂类、各种工具类、主事件循环类,几大类。
具体图形类继承图形基类及其其中的虚函数进行具体的图形实现。
画布类实现鼠标的点击,移动,释放事件控制各种图形类进行重绘,保证程序中的画笔跟随鼠标的点击拖拽进行重绘操作,达到图形跟随绘制的效果。
图形工厂类对图形进行总的管理,根据画布类返回出来的信号,创建需要的图形对象,进行设置。
工具类,主要是对图形的重绘进行修饰,边框颜色,填充颜色等等。
主事件循环类,主要是主事件在其中进行循环操作,直到用户关闭程序结束循环。

具体介绍:

Shape.h图形基类

图形基类中定义了枚举类型的ShapeType,对创建的图形进行分类,同时创建了绘画虚函数,让具体实现图形类对其进行重写,以及图形的各种移动方法,包括(拖拽、左上左下、右上右下、上下左右),以及成员变量的get和set接口。

#ifndef __K_SHAPE_H_
#define __K_SHAPE_H_
enum class KShapeType
{
	None = 0,
	Pen,
	Line,
	Circle,
	Rect,
	Pent,
	Hexa,
	Star,
	Text,
	Zoom,
};

class KShape
{
public:
	KShape();
	virtual ~KShape();
	QPoint getStartPoint();
	QPoint getEndPoint();
	void setStartPoint(QPoint point);
	void setEndPoint(QPoint point);
	QRect getShapeRect();
	bool isValid();
	// 在图形子类中进行重写, 实现不同的图形的绘制
	virtual void drawShape(QPaintDevice* parent = Q_NULLPTR) = 0;
	void drawOutline(QPaintDevice* parent = Q_NULLPTR);
	void move(QPoint offset);
	void moveTop(QPoint pos);
	void moveBottom(QPoint pos);
	void moveLeft(QPoint pos);
	void moveRight(QPoint pos);
	void moveTopLeft(QPoint pos);
	void moveTopRight(QPoint pos);
	void moveBottomLeft(QPoint pos);
	void moveBottomRight(QPoint pos);

	virtual KShapeType getShapeType();

	QString getBorderColor();
	void setBorderColor(QString col);

	QString getContentColor();
	void setContentColor(QString col);

	QString getText();
	void setText(QString str);	
private:
	QPoint m_startPoint; // 起始坐标
	QPoint m_endPoint; // 结束坐标
	QString m_borderColor = "000000"; //边框颜色
	QString m_contentColor = "FFFFFF"; //图形颜色
	QString m_text= "";
};
#endif
GlobalData.h全局数据类

全局数据类中保存的是图形的各种属性,以及获取的图形的类型,画笔的类型,当前图形,以及图形的边框颜色、内部颜色等等。

#ifndef __K_GLOBAL_DATA_H_
#define __K_GLOBAL_DATA_H_
class GlobalData
{
public:
	enum class DrawFlag
	{
		NoneFlag = 0,
		MouseFlag,
		PenFlag,
		LineFlag,
		RectFlag,
		CircleFlag,
		PentFlag,
		HexaFlag,
		StarFlag,
		TextFlag,
		ZoomFlag
	};
	static GlobalData* getGlobalDataIntance();
	static void deleteGlobalData();
	~GlobalData();
	int getCanvasWidth();
	int getCanvasHeight();
	void setCanvasWidth(int width);
	void setCanvasHeight(int height);
	void setCanvasColor(QString colorStr);
	QString getCanvasColor();
	DrawFlag getDrawFlag();
	void setDrawFlag(DrawFlag flag);
	QString getFilePath();
	void setFilePath(QString path);
	qreal getCanvasScale();
	void setCanvasScale(qreal scale);
	void setCurrentShape(KShape* shape); //设置当前图形
	Shape* getCurrentShape(); //获取当前图形
	void setBorderColor(QString str);
	QString getBorderColor();
private:
	GlobalData();
	GlobalData(const GlobalData& other)
	{}
	int m_canvasWidth = 600;
	int m_canvasHeight = 400;
	QString m_canvasColor; // 当前画布的颜色
	static GlobalData* s_globalDataObj;
	DrawFlag m_drawFlag;
	QString m_filePath;
	qreal m_canvasScale = 1;
	QString m_borderColor = "000000";
	KShape* m_currentShape = NULL;
};
#endif
svgcanvas.h

画布类定义了枚举类型的移动类型,以及重新了绘画事件、鼠标按压事件、鼠标移动事件、鼠标释放事件,对画图的具体实现进行了详细定义,点击的时候会判断是画图形还是选中图形进行移动,以及移动的方向、鼠标指针的样式以及移动过程中的update()重绘事件。

#ifndef __K_SVGCANVAS_H_
#define __K_SVGCANVAS_H_
// 移动类型(绘制图形 or 移动图形)
enum class TransType
{
	None = 0,
	TopLeft,
	Top,
	TopRight,
	Left,
	Contains,// 全部 
	Right,
	BottomLeft,
	Bottom,
	BottomRight
};
class KSvgCanvas : public QWidget
{
	Q_OBJECT
public:
	KSvgCanvas(QWidget *parent = Q_NULLPTR);
	~KSvgCanvas();
	virtual void paintEvent(QPaintEvent* event) override;
	virtual void mousePressEvent(QMouseEvent* event) override;
	virtual void mouseMoveEvent(QMouseEvent* event) override;
	virtual void mouseReleaseEvent(QMouseEvent* event) override;
	virtual void mouseDoubleClickEvent(QMouseEvent* event) override;
	KShape* getCurrentShape(QPoint pos); // 获取当前位置图形
	TransType getTransType(QPoint pos); // 获取移动类型
	QList<KShape*>* getShapeList();
	QLineEdit* getLineEdit();
	void initLineEditStyle(); // 设置文本编辑框样式
public slots:
	void saveSvg();
	void openSvg();
	void newSvg();
	void svgToPng();
	void rightBtnBackShape();
	void rightBtnDelShape();
	void rightBtnClearShape();
	void rightBtnTopShow();
	void rightBtnBehindShow();
signals:
	void transBorderColor(QString col);
	void transContentColor(QString col);
	void notSelected();
	void isSelected();
private:
	KShape* m_pCurrentShape;
	QList<KShape*>* m_pShapeList; // 存储当前画布中的图形
	QPoint m_lastPos;// 记录前一次的位置
	TransType m_TransType;// 记录移动类型
	bool m_isLPress = false; // 标记鼠标左键
	bool m_isDrawing = false; // 是否为绘图
	bool m_isSelected = false; // 是否为选中
	QLineEdit* m_lineEdit;
	QPoint point;
};
#endif
具体图形类的实现:(Rect.h)
#ifndef __K_RECT_H_
#define __K_RECT_H_
#include "kshape.h"
class KRect : public KShape
{
public:
	KRect();
	virtual ~KRect();
	virtual void drawShape(QPaintDevice* parent = Q_NULLPTR) override;
	virtual KShapeType getShapeType();
};
#endif
Rect.cpp
#include "krect.h"
#include <QDebug>
KRect::KRect()
{
}
KRect::~KRect()
{
}
void KRect::drawShape(QPaintDevice* parent)
{
	QPainter painter(parent);
	//获取边框颜色
	QPen pen(QColor(getBorderColor().toUInt(NULL, 16)));
	painter.setPen(pen);
	//获取内部颜色
	QBrush brush(QColor(getContentColor().toUInt(NULL, 16)));
	painter.setBrush(brush);
	//放缩
	qreal scale = KGlobalData::getGlobalDataIntance()->getCanvasScale(); 
	painter.scale(scale, scale); // 系统自带的放缩函数
	painter.setRenderHint(QPainter::Antialiasing);
	// 绘制矩形
	painter.drawRect(QRect(getStartPoint(), getEndPoint()));
}
KShapeType KRect::getShapeType()
{
	return KShapeType::Rect;
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Create Possible

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值