大家好,欢迎来到IT知识分享网。
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; }
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/158367.html