基于C++实现(界面)图形编辑器【100011268】

项目:图形编辑器

100011268-基于C++实现(界面)图形编辑器

一、架构图:

开发环境:

操作系统 Windows 10
编程语言 C++ 11
外部库 Qt 5.8,OpenGL
编译器 MinGW
IDE Qt Creator 4.2.1

二、功能:

  1. 新建文件,保存文件,打开文件
  2. 基本图形的绘制——直线、矩形、圆、椭圆、曲线、涂鸦笔
  3. 对图形的变换——平移、旋转、缩放
  4. 对图形的设置——颜色选择、线条粗细设置
  5. 对图形的修改——填充、删除、清除、撤销
  6. 文字编辑的插入(在代码内,但实验并不理想)

三、设计说明

3.1 矩形

矩形的类

矩形是Rectangular类和RectangularControl类来实现的,其中Rectangular类是继承SimpleFigure类,RectangularContro是继承FigureControl类。Rectangular类主要包含点的存储和矩形的底层绘图,RectangularContro类主要是存储所有的Rectangular类对象,并与qt进行交互,调用绘图界面。

矩形的生成算法

矩形的生成主要是两步:第一步是记录矩形的两个对角线角,第二步是通过两个对角线角点,来计算四条边上的像素点,再将所有像素点显示出来。

3.2 圆

Circle类继承SimpleFigure类和Area类。Circle类包含了圆的一些基本变量,圆心,半径,标记点,把手点,继承了SimpleFigure的轮廓点和Area类的填充点。Circle类提供了一些成员函数,能够对Circle对象进行一些操作,如平移,缩放,判断是否在圆上,删除,填充等。CircleControl类为操作Circle类提供了接口,实现鼠标,窗口工具栏对圆的操作,如在画布上画出图形,删除,清除,撤销等一系列操作功能。

绘制算法

圆轮廓的绘制

3.3 椭圆

椭圆的类和数据结构

椭圆的实现是由MyEllipse和EllipseControl两个类来完成的,其中MyEllipse是继承于SimpleFigure类和Area类,ElllipseControl是继承于FigureControl类。MyEllipse类的主要功能在于数学和几何方面:计算椭圆圆周上的点并存在vector中;提供椭圆的缩放、旋转和平移功能。EllipseControl则是关于椭圆的编辑操作和用户交互:用vector保存所有画过的椭圆对象(MyEllipse是其成员变量),并基于用户鼠标操作生成椭圆、平移、旋转、缩放椭圆,删除和清空所有椭圆。

椭圆的几何特征是由其圆周上所有的点和其外接矩形的顶点确定的,这些点的指针均作为成员变量保存在MyEllipse类中的vector中,可以被遍历和查找。点的颜色和大小,决定了椭圆的颜色和椭圆圆周的粗细,由MyEllipse的基类SimpleFigure来设定。

椭圆生成算法

椭圆的生成是通过计算椭圆圆周上的像素点来实现的,采用了椭圆的bresenham 算法,该算法是一种生成椭圆的整数型算法,由于整个算法当中,均采用整数运算,生成椭圆的效率比较高。

由于椭圆是中心对称图形,我们只需要计算其1/4的部分,然后根据对称规律即可得到其他三部分的点。首先,将第一象限中的图形分为两部分,区域1是图形切线斜率大于-1的部分,区域2是图形切线斜率小于-1的部分,如图9所示。

(a)区域1 (b)区域2.

图1 第一象限分区示意图 图1 第一象限分区示意图

有了上述数学分析基础,接着进行下列bresenham算法(伪代码描述):

  1. 输入椭圆的中心点坐标和长短轴长度a,b;

  2. 得到中心在原点的椭圆上的第一个点坐标(0,b);

  3. 根据公式(1.2-1)来计算初始的D值;

  4. 在区域1中,从X0=0开始,不断递增至Xk,对于每个Xk位置,反复按照公式(1.2-2)或者公式(1.2-3)来计算决策参数Dk,若Dk小于0,则Yk不变,反之Yk要减小1。重复此过程,直到区域1边界点;

  5. 在区域2中,对于每个Yk位置,从k=0开始,反复按照公式(1.2-5)或者公式(1.2-6)计算决策参数Dk,若其小于0,则Xk减少1,反之则Xk保持不变,和Xk-1一样;

  6. 根据第一象限的点,对称求出其他三个象限的坐标点;

  7. 把所有的点存入vector当中。

3.4 曲线

曲线类和数据结构

曲线的实现是由Curve和CurveControl两个类来完成的,Curve类是继承于SimpleFigure类,CurveControl是继承于FigureControl类。Curve类的主要功能在于数学和几何方面:计算曲线上的点并存在vector中;提供缩放、旋转和平移功能。CurveControl则是关于曲线的编辑操作和用户交互:用vector保存所有画过的曲线对象,并基于用户鼠标操作生成曲线、平移、旋转、缩放曲线,删除和清空所有曲线。

曲线的几何特征是由其4个顶点确定的,这些点的指针均作为成员变量保存在Curve类中的vector中,可以被遍历和查找。点的颜色和大小,决定了曲线的颜色和曲线圆周的粗细,由基类SimpleFigure来设定。

曲线生成算法

在三阶Bézier曲线中有四个控制点,设第i个控制点为,则分别为曲线的起点和终点。曲线上点的计算公式为:

从0累计到1,从而可以计算得到曲线上从的所有点。(其中每次增加0.001,以保证曲线的连续)

3.5 画笔

画笔的类和数据结构

画笔功能是通过Pen类和myPenControl类来实现的,其中Pen类是继承SimpleFigure类,myPenControl是继承FigureControl类。Pen类主要包含点的存储和线的底层绘图,myPenControl类主要是存储所有的Pen类对象,并与qt进行交互。

用户每次执行画笔功能,myPenControl便会鼠标的位置保存在Pen类对象当中,并将其显示在画布上,达到实时显示鼠标轨迹的效果。所有的Pen类对象的指针,存储在vector容器中,用于遍历、查找、删除等。

画笔的生成算法

画笔功能的算法,原理比较简单,即通过Qt捕捉鼠标移动轨迹上的点,将每个点的坐标存储在点的vector当中,然后,每保存一个点,便将所有的点遍历一遍,每两个点之间,用直线连接起来,这样就生成了一条实时的轨迹曲线。

3.6 文本框分析

文本框:如何在已有图层上插入文本是一个讨论点,我认为可以把文本框通过继承矩形类,来

  • 数据结构

文本框的设计是通过继承矩形类,然后修改矩形的构造函数,通过键盘回调函数来输入文本,保存信息到文本框类中。

  • 遇到的问题

其中思考过几种途径,包括通过模仿画笔,通过opengl库来绘制文本,但与画笔不同的是文本不能简单的通过点来制作;又思考到加载graphics库的文本绘制函数,但注意到了画布的问题。后面又考虑到QTextEdit库,但也不能输出到glwidget上来

最后采用的是Qt本身自带的QPainter来绘制,阅读说明,注意到QPainter的类构造函数中可以通过Qwidget的指针进行生成。本次项目的画布是GLWidget类的对象,是QWidget的派生类,但编译的时候一直报错,最后由于缺乏解决的渠道,未能解决这个问题。

体会:

首先由于我们的软件架构模式,我发现在矩形类对象生成的时候,根本无法找到画布GLwidget,这个问题在我们绘图,变换图形方面本身不是问题,但涉及到对画布本身进行操作的时候,感觉到了不如面向过程的编程方便,为解决这个问题,我不得不从glwidget的成员函数出发,向下一层一层的添加this指针指向glwidget。

四、使用说明

4.1 矩形

绘制

本程序绘制矩形的功能包括:根据用户鼠标拖动,生成对应的矩形,并可以设置矩形的外边框颜色、边框线条粗细。首先在已有画布的情况下,点击矩形功能,然后按下鼠标左键,并拖动,就可以得到相应的矩形,其中,鼠标移动的起点和终点是矩形的对角线角点,两点决定了矩形的位置和大小。

																		图x 矩形绘制实例

选中

只要用鼠标左键点击已有矩形的外边框,便可以选中矩形,选中的矩形,会显示四个角点,并用粉红色标记;显示中心点,用红色标记;显示把手点,用橘色标记。

平移

首先选中某个目标矩形,然后鼠标点击中心点,并拖动,则矩形将会沿着鼠标方向平移。

4.2 圆:

绘制圆

本程序可以绘制圆,在建立好画布的条件下,点击工具栏的“圆”,进入到圆绘制模式,通过点击鼠标左键,然后保持按下左键的同时拖动鼠标,松开鼠标左键后,即可画出一个圆。当拖动鼠标绘图时,鼠标拖动起始点为圆的圆心,同时生成圆的外接矩形,决定了圆的位置和大小,如图1所示。

该圆刚画出时,其外接矩形将会通过虚线标出,并显示其标记点(四个顶点、中心点和把手点),中心点和把手点之间有直线相连。

																			图1 绘制圆示意图

选中圆

当前刚绘制完的圆默认是被选中的状态,也可以选择其他已经画过的圆作为当前标记圆。选中的方法是用户的鼠标必须点击在某个圆的轮廓。

当某个圆被选中后,该圆的把手点用橘黄色标记,中心点用红色原点标记、外接矩形用蓝色虚线框显示、外接矩形四个顶点用紫色圆点显示,如图1所示。该圆会被置于所有图形的顶层。选中圆后,可以对其进行编辑操作。

圆编辑

选中某个圆后,可以对该圆进行编辑操作,包括:平移、旋转和缩放。

平移

当选中圆后,鼠标点击并拖动圆中心点,即可整体平移圆。鼠标移动的矢量即为圆的平移矢量。

缩放

用户选中目标圆后,点击圆外接矩形标记点,并移动鼠标,可以对当前圆进行放大或缩小,图2展示了缩放的示意图。

(a)选中的圆

(b)缩放之后的圆

																			图2 圆缩放示意图

填充

选择想要填充的图形,(目前,圆,椭圆,矩形可以被填充),点击工具栏中的“填充”按钮,便能对图形填充颜色。颜色默认为绿色,若想改变颜色,则需在填充之前选择颜色。图3是填充功能的展示。

(a)选中的圆 (b)填充之后的圆

																								图3 填充示意图

4.3 椭圆

绘制椭圆

本程序可以绘制椭圆,在建立好画布的条件下,进入到椭圆绘制模式,通过点击鼠标左键,然后保持按下左键的同时拖动鼠标,松开鼠标左键后,即可画出一个椭圆。当拖动鼠标绘图时,鼠标拖动起始点和终止点构成了一个矩形的对角线顶点,该矩形为椭圆的外接矩形,决定了椭圆的位置和大小,如图1所示。

该椭圆刚画出时,其外接矩形将会通过虚线标出,并显示其标记点(四个顶点、中心点和把手点),中心点和把手点之间有直线相连。

																				图1 绘制椭圆示意图

选中椭圆

当前刚绘制完的椭圆默认是被选中的状态,也可以选择其他已经画过的椭圆作为当前标记椭圆。选中的方法是用户的鼠标必须点击在某个椭圆图形内部,或者是其标记点。

当某个椭圆被选中后,该椭圆的把手点用橘黄色标记,中心点用红色原点标记、外接矩形用蓝色虚线框显示、外接矩形四个顶点用紫色圆点显示,如图1所示。该椭圆会被置于所有图形的顶层。选中椭圆后,可以对其进行编辑操作。

椭圆编辑

选中某个椭圆后,可以对该椭圆进行编辑操作,包括:平移、旋转和缩放。

平移

当选中椭圆后,鼠标点击并拖动椭圆中心点,即可整体平移椭圆。鼠标移动的矢量即为椭圆的平移矢量。

旋转

选中目标椭圆,可以看到椭圆的把手点。点击并拖动这个把手点,就可以绕着椭圆中心旋转该椭圆。由于椭圆旋转后会变形,旋转功能只是实现90°旋转,即用户拖动把手点旋转,若拖动的角度小于90°则不旋转,大于90°则整个椭圆旋转90°。椭圆旋转操作示意图如图2所示。

																			(a)选中目标椭圆

																			(b)旋转后的椭圆

缩放

用户选中目标椭圆后,点击椭圆外接矩形标记点,并移动鼠标,可以对当前椭圆进行放大或缩小,图3展示了缩放的示意图。

											(a)选中的椭圆  (b)缩放之后的椭圆

4.4 曲线

绘制曲线

本程序可以绘曲线,在建立好画布的条件下,点击工具栏的“曲线”,进入到曲线绘制模式,通过点击鼠标左键,然后在任意位置画下四个点,即可绘制出曲线。

该曲线刚画出时,其外接矩形将会通过虚线标出,并显示其标记点(四个顶点、中心点和把手点),中心点和把手点之间有直线相连。

选中曲线

当某个曲线被选中后,该曲线的把手点用橘黄色标记,中心点用红色原点标记、四个顶点用紫色圆点显示,如图1所示。该圆会被置于所有图形的顶层。选中圆后,可以对其进行编辑操作。

曲线编辑

选中某个曲线后,可以对该曲线进行编辑操作,包括:平移、旋转。

平移

当选中曲线后,鼠标点击并拖动中心点,即可整体平移。鼠标移动的矢量即为曲线的平移矢量。

4.5 画笔

本程序的画笔功能是:由鼠标操作,实现任意曲线的绘制。结合设定颜色和线宽,用户可以根据自己需要画出任意的曲线和曲线组合图案。

首先,在一块画布上,点击“画笔”工具,便开启了画笔模式,此后,按下鼠标左键,并拖动,就可以在画布上实时画出曲线。鼠标移动轨迹,即为线条的轨迹。若松开鼠标左键,则画笔功能停止;再次按下鼠标左键,可继续进行绘制轨迹曲线。如图4所示,使用画笔,可以画出鼠标移动轨迹。

由于画笔要实现的是画出任意轨迹曲线的功能,故没有选中、旋转和缩放功能。

																图4 画笔使用实例

4.6 删除、清除、撤销:

在软件中,每一个生成的图像都作为一个Figure类保存在vector容器中,每一次删除操作,都把该图像从vector容器中删除,加入到另一个保存历史记录的vector中,以先进后出的原则实现撤销的操作。使用“清除”后,Figure类vector容器中所有的元素都被删除,所以无法被撤销。

删除:选中图形后,点击“删除”按钮,即可删除图形。

清除:点击“清除”按钮,即可清空画布上的所有图形。

撤销:在删除图形后,可点击工具栏中的“撤销”按钮,即可恢复上一次被删除后的图形。

“撤销”功能无法恢复被“清除”的图形。

具体操作可看操作视频。

五、测试分析

5.1 矩形

绘制

测试了矩形的绘制,不同的鼠标移动轨迹是否可以生成对应的矩形。同时测试了设定不同的颜色和宽度,发现都可以实现。测试表明矩形功能复合设计要求。

																					图10 矩形测试实例

平移

对原始矩形进行平移,如图所示。除了图中实例之外,我们还对目标矩形进行了多方向、连续移动,发现均能实现。在有多个矩形的画布中,也可以实现对选中矩形的平移。

																	(a)原始目标矩形  (b)平移后的矩形

																						图11 矩形平移测试实例

5.2 圆测试

绘制

鼠标点击拖动,绘制不同位置、不同形状、不同颜色和线宽的圆。如图3所示,根据测试,绘制圆功能正常。

												(a)多个圆、任意位置和大小,不同线宽,颜色

平移

选中目标圆,对其进行平移操作,测试情况如图4所示。多次平移测试表明,圆可以实现任意平移操作,平移功能正常。

																		(a)目标圆  (b)平移后的圆

缩放

对目标椭圆进行缩放,如图5所示。对目标椭圆,可以进行任意放大和缩小,多次测试表明,缩放功能正常,填充图形也能正常缩放。

																(a)目标圆1  (b)放大目标圆1

5.3 椭圆测试

绘制

鼠标点击拖动,绘制不同位置、不同形状、不同颜色和线宽的椭圆。如图4所示,根据测试,绘制椭圆功能正常。

															(a)横向椭圆  (b)纵向椭圆

								(c)多个椭圆、任意位置和大小  (d)多个椭圆,不同线宽、不同颜色

平移

选中目标椭圆,对其进行平移操作,测试情况如图5所示。多次平移测试表明,椭圆可以实现任意平移操作,平移功能正常。

																(a)目标椭圆  (b)平移后的椭圆

旋转

对目标椭圆进行旋转操作,使得该椭圆旋转90°。经过对不同椭圆进行旋转测试,发现均可以实现正常的旋转功能。

															(a)长轴水平的椭圆	(b)旋转之后的椭圆
        	          
															(c)长轴竖直的椭圆	(d)旋转之后的椭圆

缩放

对目标椭圆进行缩放,如图7所示。对目标椭圆,可以进行任意放大和缩小,多次测试表明,缩放功能正常。

																	  (a)目标椭圆 	(b)缩小     
      	          
																	  (c)目标椭圆2	(d)放大目标椭圆2

5.3.1 曲线测试

绘制

鼠标点击拖动,绘制不同位置、不同形状、不同颜色和线宽的曲线。根据测试,绘制曲线功能正常。

平移

选中目标曲线,对其进行平移操作,测试情况如图所示。多次平移测试表明,曲线可以实现任意平移操作,平移功能正常。

旋转

对目标曲线进行旋转操作,使得该曲线旋转任意角度,发现均可以实现正常的旋转功能。

5.3.2 画笔

本程序画笔支持用户设定颜色、设定线宽,来画出曲线。如图8所示,可以用画笔功能画出任意曲线,也可以在同一画布当中画出多条曲线,并可以设定不同的颜色和线条宽度。测试表明,画笔可以实现设定功能。

(a)简单曲线 (b)多条曲线、多种颜色和线宽

总结

经验

本次大程序设计,能够帮助我们进一步地理解面向对象编程设计。在实现类的过程中,发现了类的设计需要提前精心的设计,在实现类的过程中了解到了类的设计和实现的不易,但在扩展性方面又有很大的便利。本次大程序的作业过程中,也让我们体会到了团队合作的重要性。

♻️ 资源

在这里插入图片描述

大小: 26.9MB
➡️ 资源下载:https://download.csdn.net/download/s1t16/87575070
注:如当前文章或代码侵犯了您的权益,请私信作者删除!

猜你喜欢

转载自blog.csdn.net/s1t16/article/details/131652773
今日推荐