C#Winform简易矢量图绘制系统(含进度条、登录、新建、导入、导出、画布、绘画等)

简易矢量图绘制系统
本系统为一个简易的矢量图绘制系统,现就本系统的功能进行描述,同学们
在完成表述功能的基础上可以进行进一步的拓展。
1、总则:选择 VS2015 进行开发,Framework 为 4.5 及以下版本,类、方法、
必须给出必要的注释。命名做到见名知意。代码力求简洁明确。对大作业的考察
将从知识、技能、综合、创新角度进行。
2、开始界面:800*500 窗体,居中显示,有背景图片及“简易矢量图绘制系
统”字样,停留时间为 3~5 秒。开始界面结束后自动关闭,并进入登陆界面(可
参照 VS 的启动界面)。可配滚动条或转动动画等表示等待程序加载。
3、登陆界面:包括两个文本编辑框“用户名”、“密码”,用户名、密码等信息
可存储在文件中,或直接写在程序里。包括两个按钮“确定”、“取消”,点击确定
判断用户名、密码是否正确。当用户名密码有误时,弹出提示窗口,直到输入正
确,关闭登陆界面进入程序主界面。取消按钮按下直接退出程序。
4、主界面:左下角或右下角显示系统时间,刷新间隔为 1 秒,此处开辟(启
动)一个线程单独处理系统时间的刷新显示。须使用菜单、工具栏。菜单栏在主
界面最上方,工具紧贴在菜单栏下方。菜单项至少包含“文件”、“颜色”、“帮助”。
文件项至少包含“打开”、“新建”、“保存”、“退出”子项。打开子项可加载已保存过
的图形文件,新建子项可新建绘图并将窗体的背景改为白色。保存子项需要实现
对图形的保存,可保存成图片格式,也可保存成图元格式。退出子项可退出程序。
帮助项须实现打开浏览器功能。工具栏须体现可绘制的所有图形的种类,包括但
不限于,矩形、椭圆、直线。可绘制折线图、(不规则)多边形。图形绘制过程,
随刷新不断显示(鼠标移动时不断显示绘制的图形)。图形可根据窗体大小改变
而缩放。应尽量减少绘制过程的闪烁。
5、制作安装文件:针对“简易矢量图绘制系统”制作安装文件,安装包内无需
提供 Framework 安装文件。

在欢迎界面添加ProgressBar控件和Timer控件,在Timer的Tick事件中添加相关代码,使得进度条随着时间不断增加,同时添加一个Label可以实现数字加载显示。在绘制主界面添加一个Label,在窗体load函数中创建一个线程获得当前时间,可以实时显示在Label文本上。在主界面添加onpaint函数,使得绘画时在内存中新建画布,一次性显示,减少绘制过程中的闪烁。

3 运行效果说明
1、首先给出的是欢迎界面的运行情况,如图2所示。中间有“欢迎使用简易矢量图绘制系统”字样,下方有加载进度条显示,进度条旁边则为更加具体的数字显示。

图2 欢迎界面运行效果图

2、欢迎界面停留3~5秒后,然后进入登录界面。界面包含两个标签,分别是两个Label,分别设置它们的Text为“用户名”和“密码”;两个文本框TextBox,用来获取用户输入内容;两个按钮Button,分别命名为btn_OK和btn_Cancel,Text设置为“确定”和“取消”,“确定”按钮用来判断用户名和密码是否输入正确,“取消”按钮可以退出整个程序。如图3所示。

图3 登陆界面运行效果图
3、登录成功后进入绘制的主界面。主界面上方有菜单栏、工具栏,菜单栏具有“文件、颜色、帮助”菜单,而“文件”菜单具有“打开、新建、保存、退出”四个菜单项。主界面右下角有状态栏,实时显示当前时间。如图4所示。

                       图4 绘制主界面运行效果图

4、在菜单“文件”下拉菜单项点击“打开”可以打开图片,进行绘制。如图5、6所示。

               图5 菜单项“打开”运行效果图(1)

图6 菜单项“打开”运行效果图(2)

5、菜单“颜色”点击会打开一个颜色选择框,供用户选择颜色进行绘制。如图7所示。

                        图7 颜色选择框

6、点击“文件”下拉菜单“新建”后,再任意选择工具栏中的一个就可以绘制相应图形,工具栏含有“铅笔、直线、矩形框、椭圆、文字、橡皮、折线、不规则图形”等多种形状工具。如图8所示。若用户想重新画,可以再次点击“新建”,此时画布上的图画会清空。

图8 绘制主界面运行效果图
7、用户绘制完成后,可以点击“文件”下的“保存”,自行选择保存格式、保存名称和保存路径。如图9所示。

                          图9 保存窗口

8、点击菜单“帮助”会自动打开默认浏览器的百度页面,帮助用户搜索。如图10所示。

                       图10 帮助功能显示

4 实现难点及解决方案

4.1 系统时间的显示刷新难点
难点赘述:如果要实现开辟一个线程单独处理系统时间的显示刷新功能,可以采用Timer控件来实现,但是Timer控件会消耗系统资源。
解决方法:可以转为采用线程处理,由于线程调用方法不支持控件处理模式,故采用委托方法实现。
已知,线程是程序执行流的最小单元,如果把进程比作一条河流,那么线程就是河流的一条小支流。他是独立执行,却可能对主进程有影响。
而对于单线程与多线程而言,单线程就是,任务一个一个地做,必须做完一个任务后,再去做另一个任务。多线程就是一会做这个任务,一会做那个任务,每个任务做一会,不停的切换。显然,最后把所有的任务做完,多线程必定比单线程更耗费时间。为什么?因为,多线程要在不同的任务之间切换,切换肯定是要耗费时间的。那么问题来了,既然多线程比单线程更耗费时间,为什么还要多线程? 单线程有一个致命的问题,就是一个线程运行的整个过程中,其他线程必须等待,不能响应用户的命令,体验太差,好像电脑死机一样,所以,我们在解决该问题时采用单独开辟个线程单独处理系统时间的显示刷新的方法,使得系统显示时间可以实时刷新,并在系统资源有限的前提下节省系统资源。

4.2 在PictureBox中绘图防止闪烁难点
难点赘述:在课程设计的过程中,我需要在窗体上进行图片的绘制,但是在实际的测试中发现了问题,那就是重绘的时候会发生闪烁
解决方法:双缓冲防止闪烁,我们首先来探讨下为什么重绘的时候会发生闪烁:如果我们先以背景色填充,然后再填充绘制新画面,就会造成这个空白的画面由于和人眼中原本残留的图像反差非常大,所以便会破坏视觉残留产生的画面,给人的感觉就是,这个画面在不停的闪烁。
对此,我们可以将窗体的Double Buffered属性设置为true,或者通过继承或者反射机制,将pictureBox的Double Buffered属性设置为true,但是经过实验,这些方法都不大灵光。
经过多方查证,我发现我们这个问题所遇到的障碍就是不能影响pictureBox的背景图的展示,为此我们可以把pictureBox的背景图片也提取出来,作为底层画布,pictureBox的Refresh()方法不会影响其背景层,所以我们将最后合成的画布直接贴在背景层上,这样再Refresh()就不会产生闪烁了,同时,由于系统会自动重绘背景层,所以在窗口最小化或者被遮挡过后,绘制的图像也不会消失,相当于不用手动重绘,至此,闪烁问题就彻底的被解决了。
4.3 进度条的显示难点
难点赘述:难点为了将欢迎界面做的美观,需要添加加载图画或者进度条显示。我在进行尝试的过程中遇到了出现异常、断点等困难。故选择它作为难点。
解决方法:首先我选择的是用label作为载体,加载gif图标的方法显示加载画面,但是由于它加载时的图标显示不稳定且不能和原来设置的界面停留代码sleep函数很好兼容,所以我选择了另一种方法。
通过查找资料,我发现C#内置了一种控件可以实现进度条显示的功能。因为这个控件的使用,需要timer控件相配合,所以我添加timer控件后,在timer的事件tick函数中添加它的进度条值的变化,即 a += 1; progressBar1.Value = a;同时在欢迎界面的load函数中设置刷新时长为1秒,即timer1.Interval = 1000;另外还有一些基础设置在这里不做过多赘述,总之,这种方法可以同时实现欢迎界面的停留和进度条加载的功能,所以我最后选择使用这个方法。
4.4 折线绘制的实现难点
难点赘述:折线的绘制难点在于直线与直线之间如何衔接起点和终点,如何将这部分代码做的简洁又有效,如何减少绘制中的闪烁问题。
解决方法:折线的绘制,从功能分析上可以理解为在直线的基础上当用户到达直线终点时停顿,即用户将鼠标拿起,此时系统显示用户画出一条直线,当用户再次按下时,将上一条直线的终点作为起点进行绘制,而用户进行移动时只需要不断获取终点即可。因此添加了count变量作为点击次数的标记,当count归零时可以重新进行绘制,添加isstart变量存储绘制的起点,fistPoint作为第一个绘画点,endPoint作为绘制终点。然后就可在switch语句和工具栏中相应按钮中Click事件中添加相关代码,完成所需的绘制功能。此外为了使得绘制时减少闪烁的程度,添加了一个函数onpaint,在内存中新建画布,即Graphics g = this.CreateGraphics();Bitmap localbitmap = new Bitmap(ClientRectangle.Width, ClientRectangle.Height); Graphics bg = Graphics.FromImage(localbitmap); bg.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;存储画面然后一次性显示,即添加如下代码if (theImage != null) {bg.DrawImage(theImage, 0, 0);}这样就会减少闪烁,增加用户的体验效果。
4.5 窗口与控件的自适应难点
问题赘述:考虑到不同的电脑分辨率不同导致窗体展不开、窗口的缩放会导致控件变化位置、不再美观等问题,然后进行了一系列修改,遇到了很多问题。
解决方法:可以通过对控件的尺寸进行重置来实现窗体的自适应功能,即先将原窗体的初始值进行存储,然后通过SizeChange事件响应窗体改变,实现重绘。缩放的解决方案是首先定义两个全局变量分别为窗体的高、宽,将控件的宽、高,左边距和字体大小暂存到tag属性中,通过功能函数setTag递归控件中的控件,通过setControls遍历窗体中的控件,重新设置控件的值,在窗体的load事件中添加代码,用于获取窗体的宽、高,并调用方法setTag(),在窗体的Resize事件中添加,窗体宽、高的缩放比例,随窗体改变控件大小。
注意事项:获取初始值的方法应该在构造函数中,而不是Load事件中。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

次郎不小

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

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

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

打赏作者

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

抵扣说明:

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

余额充值