很久没发技术文章了啊……被人说装文艺了啊……我在乱说些啥吗…………
最近学校开了数据结构的课设设计,说是允许使用C++,Java和C#来进行开发。Java上上个学期学的,说实话,感觉真的不是很爽……或许是我电脑的缘故,也或许是心理作用,我总觉的NetBeans一开就卡得不行!无论怎样都得不到在VS中开发和调试的那种爽快感,于是一度打算投奔C++的阵营,还为此买了Qt的书来学习,不过由于一直以来被诸多事情所扰(懒?),Qt的学习就停留在了……编译完毕。好吧,我输了……C#,就决定是你了!
那么进入正题吧。
在课程设计的过程中,我需要在窗体上进行图片的绘制,但是在实际的测试中发现了问题,那就是重绘的时候会发生闪烁,这个问题其实在大一的C语言课设的时候就出现过了,在程序绘制动画的高频率刷新的时候,也会产生闪烁,而那时候的解决办法,是对动画进行双缓冲(Double Buffering)处理。
在被双缓冲这个名词吓到之前,我们先来探讨下为什么重绘的时候会发生闪烁:
说道动画的原理大家都懂,就是利用了人眼的视觉残留(Visual staying)现象,当一副画面进入人眼成像后,并不会立刻消失,而是仍会保留一小段时间,于是当连续的图像以很高的速度切换的时候,人眼会看到动态的影响,而不是处于切换中的单个图像。
这个过程可以参考图1:
Step 1: 将C以背景色填充(也就是清除C上现有的内容)
Step 2: 在C上按照要求绘制新的画面
那么这样的过程会对动画产生怎样的影响呢?请看图2:
画布g是透明的,所以在g上绘制后,贴在pictureBox上,背景图片还是会展示出来,但是问题也就来了,由于pictureBox的绘制机制问题,如果我在pictureBox上贴一张透明的图,其效果就是这样的:
// 初始化画板Bitmap image = new Bitmap(pictureBox1.ClientSize.Width, pictureBox1.ClientSize.Height); // 获取背景层Bitmap bg = (Bitmap)pictureBox1.BackgroundImage; // 初始化画布Bitmap canvas = new Bitmap(pictureBox1.ClientSize.Width, pictureBox1.ClientSize.Height); // 初始化图形面板Graphics g = Graphics.FromImage(image);Graphics gb = Graphics.FromImage(canvas); // 绘图部分 Begin// ... ...// 绘图部分 End gb.DrawImage(bg, 0, 0); // 先绘制背景层gb.DrawImage(image, 0, 0); // 再绘制绘画层 pictureBox1.BackgroundImage = canvas; // 设置为背景层 pictureBox1.Refresh();pictureBox1.CreateGraphics().DrawImage(canvas, 0, 0); |
注意我标注的行,就是添加的部分。
pictureBox的Refresh()方法不会影响其背景层,所以我们将最后合成的画布直接贴在背景层上,这样再Refresh()就不会产生闪烁了,同时,由于系统会自动重绘背景层,所以在窗口最小化或者被遮挡过后,绘制的图像也不会消失,相当同时于免去了手动重绘之苦。这样一来,困扰我们的闪烁问题就彻底的被解决啦!
感觉自己不知不觉废了好多话呀……啦啦啦,这篇就到这喽。
联系客服