# 面向对象图形实验
**Repository Path**: hrzheng/oop_graphic
## Basic Information
- **Project Name**: 面向对象图形实验
- **Description**: 面向对象图形实验
- **Primary Language**: Python
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 2
- **Forks**: 0
- **Created**: 2021-06-05
- **Last Updated**: 2023-02-21
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# 基础图形绘制软件
- 作者:郑浩然
- 学号:181860147
- 专业:计算机科学与技术
- 仓库地址:https://gitee.com/hrzheng/oop_graphic
## 1.引言
本项目是采用python的`tkinter`框架完成的一个图形绘制小程序,包含**线段、椭圆、圆形、矩形、三角形**的图形绘制,图形移动,图形合并,改变图形大小,更改图形颜色,添加文字描述,查看文字描述,复制图形,粘贴图形,保存,撤销的功能。
每个绘制的独立的图形为一个`Basic`类,线段、椭圆等图形均继承自`Basic`类。显示在屏幕上的图形以`Shape`类存在,`Shape`类维护了多个`Basic`类,从而以此实现图形的组合。
`MyCanvas`是`tkinter`基础画布类型`Canvas`的继承,在通过在其中放置多个`Shape`来实现图形的显示。
`Originator`是备忘录类,在其中记录了画布中图形的上一个状态,通过将画布中图形恢复为`Originator`中记录的状态实现画布上的撤销操作。
## 2.分析与设计
### UML建模

### 设计模式
- 单例模式:`MyCanvas`是一个单例,因为在其继承自`Canvas`画布,而在一个`tkinter`窗口中只能包含一个画布,因此`MyCanvas`也是一个单例,所有的图形都显示在此画布上。
- 组合模式:`Shape`类中包含一个`basic_list`,通过`addBasic`函数将一个具体的`Basic`添加入`Shape`,从而实现图形的组合。
- 备忘录模式:`Originator`为一个备忘录类,在界面中点击`保存`按键,就可以将当前画布上的图形状态保存在备忘录中。当点击`撤回`时,就会按照备忘录中记录的状态将画布中当前图形更改为备忘录中记录的图形状态,从而实现撤销功能。
## 3.实现方案
### 数据结构:
##### `Basic`
本类为基础图形的抽象类,有具体子类`Line, Rectangle, Triangle, Ellipse, Round`,这里只讲解抽象类`Basic`.
###### 变量:
- `id`:使用`tkinter`函数创造图像时返回的数值,通过此id可以实现图形移动等操作
- `tag`:使用全局函数`randstr()`生成的四位随机字符串,作为图形的唯一标识
- `shape`:标识图形形状的字符串
- `color`:图形的颜色
###### 函数:
- `moveBasic()`:使用`tkinter`的move函数移动图形
- `createBasic()`:使用`tkinter`的create函数创造图形
- `changeColor()`:重新创造一个指定颜色的新图形实现颜色的更改
- `largenBasic()`:重新创造一个更大的新图形实现图形的放大
- `lessenBasic()`:重新创造一个更小的新图形实现图形的缩小
##### `Shape`
组合图形类,本类维护了一个存储基础图形类的列表,从而实现图形的组合。在画布上显示的所有图形都封装在`Shape`类中。
###### 变量:
- `basic_list`:用于存储`Basic`类的列表
- `txt_list`:用于存储文字描述的列表
- `shape_tag`:用于区分本`Shape`的唯一标识
- `color`:本`Shape`中所有图形的颜色
###### 函数:
- `addBasic()`:向`Shape`中添加新的图形,用于实现图形的组合
- `moveShape()`:调用每个图形的`moveBasic()`函数实现组合图形的移动
- `addTxt()`:向组合中添加文字描述
- `getTxt()`:读取组合的文字描述
- `mergeShape()`:实现图形之前的组合
- `createShape()`:调用每个图形的create函数创造一个新的图形组合
- `changeColor()`:调用每个图形的`changeColor()`函数改变每个图形的颜色
- `largenShape()`:调用每个图形的`largenBasic()`函数放大每个图形
- `lessenShape()`:调用每个图形的`lessenBasic()`函数缩小每个图形
##### `Originator`
备忘录类,维护了一个旧状态的列表实现撤销操作
###### 变量:
- `old_shape_list`:用于维护画布中图形的的旧状态的列表
###### 函数:
- `changeStatus`:点击保存是更新`old_shape_list`为一个新的状态
##### `MyCanvas`:
本类为画布类,继承自`tkinter`的`Canvas`,因此是一个单例。所有的图形都在本类中显示。
###### 变量:
- `shape_list`是一个列表,用来记录画布中的所有组合图形
- `flag`用来记录当前选择的状态,包含新建、移动、复制、粘贴等
- `item_type`用来记录当前选择的图形样式,包括线段、矩形、椭圆等
- `cv`为`Canvas`类的实例,实现基础的画布功能
- `originator`为备忘录类`Originator`的实例,实现保存和撤销功能
###### 函数:
- `init()`:包含了多个`init`函数,包括`init_canvas(), init_menu(), init_label(), init_bind()`,分别用于对画布,菜单栏,下方标识栏,按钮的初始化
- `choose_move()`:用于更改`flag`,从而更改当前的功能
- `getShape()`:包含`getShape(), getShape_notself()`,前者用于获取当前鼠标所在位置对应的`Shape`类,后者用户合并图形时,获取当前位置除了自己外的其他`Shape`类
- `lagen()`:放大当前位置的`Shape`
- `lessen()`:缩小当前位置的`Shape`
- `changeColor()`:更改当前位置`Shape`的颜色
- `renew_shape_list()`:将维护的`shape_list`更改为备忘录中记录的`shape_list`,实现撤销操作
- `revocation()`:撤销操作
- `reset()`:还原临时参数的状态为初始值
- `addTxt()`:对图形添加描述
- `showTxt()`:展示图形的描述
- `paste()`:粘贴,其中使用了`shapePaste()`函数
- `copy()`:复制一个`Shape`并将其保存在`copy_shape`中
- `move()`:图形的移动操作,包含`StartMove(), StopMove(), OnMove()`,分别表示开始移动,停止移动,移动中

- `create()`:图形的新建操作,包含`StartCreate(), StopCreate(), OnMotion()`,分别表示开始新建,停止新建,新建中。新建时图形为虚线,松开鼠标之后产生一个实线的图形

- `drag_handler()`:创建图形时不断生成虚线图形的操作
## 4.功能介绍
#### 1.新建
**若是不在选择按钮中选择想要进行的操作,则默认进行新建操作。**选择右上角**选择**按钮中的新建按钮,便可以在画布中拖动新建一个新的图形,想要新建的图形在图形按钮中选择,**默认为矩形**
#### 2.移动
选择右上角**选择**按钮中的移动按钮,便可以在画布中拖动图形移动
若是将一个图形移动到另一个图形上时,两个图形便会进行组合,合并为一个整体
#### 3.添加文字描述/查看文字描述
选择右上角**选择**按钮中的添加文字描述/查看文字描述按钮,便可以在画布中点击图形插入文字描述/查看文字描述
#### 4.复制/粘贴
选择右上角**选择**按钮中的复制按钮,便可以在画布中点击对应图形进行复制;之后点击粘贴按钮,点击想要粘贴的位置,便可以将选中的图形粘贴到相应位置
#### 5.改变颜色
选择右上角**配置**按钮中的改变颜色按钮,点击选中的图形/组合便可以更改颜色,**颜色按照固定的顺序变更:无色,红色,黄色,蓝色,绿色**
#### 6.改变图形大小
选择右上角**配置**按钮中的放大图形/缩小图形,点击选中的图形/组合便可以更改图形大小
#### 7.保存/撤销
选择右上角**文件**按钮中的保存,即可保存当前的画布图形。之后进行若干步操作之后,点击撤回,便可以将画布撤回至保存时的画布样式
## 5.环境配置
- 使用pycharm打开`main.py, basic.py, shape.py, originator.py`
- 运行`main.py`,我使用的是python3.9版本