winform panel里面放了一个control,在control上绘图,放大时存在闪烁现象。

问题描述

主要是在一个Panel上面放了一个继承Control的控件,Dock模式为Fill,主要的绘图区域为Control。.net版本为2.0,winform的程序。在进行放大和缩小的时候出现了闪烁的现象,具体原因可能为paint2次绘制导致。其中放大部分代码为:publicvoidDrawZoomIn(){scale=scale/ampfactor;Pointpt=GetDisplayCenter();//获取当前显示中心intiwidth=(int)(Width/ampfactor);//ampfactor是放大系数intiheight=(int)(Height/ampfactor);//对长和宽进行长度限制if(iwidth>7000||iheight>7000){scale=scale*ampfactor;return;}this.Size=newSize(iwidth,iheight);//对滚动条进行控制if(iwidth>=rcclient.Width){pt.X=(int)(pt.X/ampfactor-rcclient.Width/2);pt.Y=(int)(pt.Y/ampfactor-rcclient.Height/2);owner.AutoScrollPosition=pt;//owner为control的容器panelpanel的autoscroll属性为true}}

在paint部分的代码为privatevoidDrawArea_Paint(objectsender,PaintEventArgse){if(e.ClipRectangle.Width==0||e.ClipRectangle.Height==0){return;}DrawGrid(e.Graphics);//绘制网格_graphicsList.Draw(e.Graphics,scale,ClientRectangle);//绘制保存的矩形、线等}

其中Panel和Control里面都设置了双缓冲,双缓冲代码为(panel自己写了一个继承panel的类)this.SetStyle(ControlStyles.OptimizedDoubleBuffer|ControlStyles.ResizeRedraw|ControlStyles.Selectable|ControlStyles.AllPaintingInWmPaint|ControlStyles.UserPaint|ControlStyles.SupportsTransparentBackColor,true);this.UpdateStyles();

解决方案

解决方案二:
那个WinForm重绘。好像官方的说法是:只绘制无效的区域,而不要全部区域都绘制。当然:绘制线段,颜色应该不损耗效率——但是,绘制图片往往很卡。GDI绘图,有点卡——再所难免。
解决方案三:
引用1楼sxl514286339的回复:

那个WinForm重绘。好像官方的说法是:只绘制无效的区域,而不要全部区域都绘制。当然:绘制线段,颜色应该不损耗效率——但是,绘制图片往往很卡。GDI绘图,有点卡——再所难免。

因为放大后,我调整了显示区域,所以我就全部进行了绘制。关于绘制图片部分,其实就是一些多线段而已,并且多线段并不复杂的。100条线都没有到。
解决方案四:
莫非楼主电脑很卡?
解决方案五:
或者,楼主试试:你要使用DrawArea控件的Paint事件。而是DrawArea自身继承Control的OnPaint方法。
解决方案六:
引用4楼sxl514286339的回复:

或者,楼主试试:你要使用DrawArea控件的Paint事件。而是DrawArea自身继承Control的OnPaint方法。

不是很明白,这句话啥意思。
解决方案七:
引用4楼sxl514286339的回复:

或者,楼主试试:你要使用DrawArea控件的Paint事件。而是DrawArea自身继承Control的OnPaint方法。

电脑绝对不卡,用的都是最新的CPU和硬件的。
解决方案八:
publicclassMyControl:Control{protectoverridevoidOnPaint(Event??Arge){base.OnPaint();e.Grap**.Draw(Image.ImageFrom("D:AAAA.png"));}}——然后看这个控件卡补卡。
解决方案:
1.检查下是否存在循环事件(绘图过程中触发绘图事件)2.检查下单次绘图耗时
解决方案:
引用6楼kwfly的回复:

Quote: 引用4楼sxl514286339的回复:
或者,楼主试试:你要使用DrawArea控件的Paint事件。而是DrawArea自身继承Control的OnPaint方法。

电脑绝对不卡,用的都是最新的CPU和硬件的。

跟显卡有关系,不是说CPU配置高就无敌了
解决方案:
1.在DrawArea里面设置双缓冲。2.双缓冲原理是先绘制到一个Bitmap上,再将Bitmap拷贝到DrawImage到控件上。(惭愧,我没深究过第1点处设置了双缓冲后这里是不是就可以直接使用Graphics绘图)3.如果使用双缓冲并且是在OnPaint上面绘图,之后还会有闪烁的问题,那你就得看看OnPaint里面做了太多/久/耗性能的事情。总之:你在OnPaint中先绘到一个与控件一样大小的Bitmap上,绘制完成再将Bitmap拷贝(DrawImage)上控件。
解决方案:
引用10楼Yokeqi的回复:

1.在DrawArea里面设置双缓冲。2.双缓冲原理是先绘制到一个Bitmap上,再将Bitmap拷贝到DrawImage到控件上。(惭愧,我没深究过第1点处设置了双缓冲后这里是不是就可以直接使用Graphics绘图)3.如果使用双缓冲并且是在OnPaint上面绘图,之后还会有闪烁的问题,那你就得看看OnPaint里面做了太多/久/耗性能的事情。总之:你在OnPaint中先绘到一个与控件一样大小的Bitmap上,绘制完成再将Bitmap拷贝(DrawImage)上控件。

双缓冲原理还是清楚的,在MFC里面都是采用你说的方法做的,突然换到C#里面有自己提供的缓冲所以就没有进行处理。刚测试了一下,OnPaint里面如果完成绘图一次的操作大概需要15ms。里面画网格部分没有优化,全部采用所有线全部画一遍。
解决方案:
引用8楼assky124的回复:

1.检查下是否存在循环事件(绘图过程中触发绘图事件)2.检查下单次绘图耗时

单次绘图耗时为15ms左右。绘图操作确实执行了两次,但是不存在循环绘图的情况。一个是调整Panel的Scroll位置的时候进行了绘制。一个是调整继承自Control也就是绘图控件的大小的时候产生了重绘的操作。
解决方案:
引用11楼kwfly的回复:

Quote: 引用10楼Yokeqi的回复:
1.在DrawArea里面设置双缓冲。2.双缓冲原理是先绘制到一个Bitmap上,再将Bitmap拷贝到DrawImage到控件上。(惭愧,我没深究过第1点处设置了双缓冲后这里是不是就可以直接使用Graphics绘图)3.如果使用双缓冲并且是在OnPaint上面绘图,之后还会有闪烁的问题,那你就得看看OnPaint里面做了太多/久/耗性能的事情。总之:你在OnPaint中先绘到一个与控件一样大小的Bitmap上,绘制完成再将Bitmap拷贝(DrawImage)上控件。

双缓冲原理还是清楚的,在MFC里面都是采用你说的方法做的,突然换到C#里面有自己提供的缓冲所以就没有进行处理。刚测试了一下,OnPaint里面如果完成绘图一次的操作大概需要15ms。里面画网格部分没有优化,全部采用所有线全部画一遍。

也可能,不是你重绘的问题,而是Form在画Panel的时候产生的闪烁。C#有个很不爽的地方是Form上的控件一多显示的时候就会闪烁。所以你可以首先试试把你这个重绘的做法单独做在一个Form上,然后用弹出框的方式弹出来看看是否会闪烁,如果不会那基本就能确定是因为那个Panel什么的问题而不是你这些重绘代码的问题了。相应的解决方案相信你也就有了。
解决方案:
开双缓存。
解决方案:
引用13楼Yokeqi的回复:

Quote: 引用11楼kwfly的回复:
Quote: 引用10楼Yokeqi的回复:
1.在DrawArea里面设置双缓冲。2.双缓冲原理是先绘制到一个Bitmap上,再将Bitmap拷贝到DrawImage到控件上。(惭愧,我没深究过第1点处设置了双缓冲后这里是不是就可以直接使用Graphics绘图)3.如果使用双缓冲并且是在OnPaint上面绘图,之后还会有闪烁的问题,那你就得看看OnPaint里面做了太多/久/耗性能的事情。总之:你在OnPaint中先绘到一个与控件一样大小的Bitmap上,绘制完成再将Bitmap拷贝(DrawImage)上控件。

双缓冲原理还是清楚的,在MFC里面都是采用你说的方法做的,突然换到C#里面有自己提供的缓冲所以就没有进行处理。刚测试了一下,OnPaint里面如果完成绘图一次的操作大概需要15ms。里面画网格部分没有优化,全部采用所有线全部画一遍。

也可能,不是你重绘的问题,而是Form在画Panel的时候产生的闪烁。C#有个很不爽的地方是Form上的控件一多显示的时候就会闪烁。所以你可以首先试试把你这个重绘的做法单独做在一个Form上,然后用弹出框的方式弹出来看看是否会闪烁,如果不会那基本就能确定是因为那个Panel什么的问题而不是你这些重绘代码的问题了。相应的解决方案相信你也就有了。

感谢帮忙分析。目前测试情况为,将owner.AutoScrollPosition=pt;//owner为control的容器panelpanel的autoscroll属性为true上面这句话去掉之后就看不到闪烁的情况了。但是panel的滚动条都变为了0位置,不是我想要的居中效果。
解决方案:
引用15楼kwfly的回复:

Quote: 引用13楼Yokeqi的回复:
Quote: 引用11楼kwfly的回复:
Quote: 引用10楼Yokeqi的回复:
1.在DrawArea里面设置双缓冲。2.双缓冲原理是先绘制到一个Bitmap上,再将Bitmap拷贝到DrawImage到控件上。(惭愧,我没深究过第1点处设置了双缓冲后这里是不是就可以直接使用Graphics绘图)3.如果使用双缓冲并且是在OnPaint上面绘图,之后还会有闪烁的问题,那你就得看看OnPaint里面做了太多/久/耗性能的事情。总之:你在OnPaint中先绘到一个与控件一样大小的Bitmap上,绘制完成再将Bitmap拷贝(DrawImage)上控件。

双缓冲原理还是清楚的,在MFC里面都是采用你说的方法做的,突然换到C#里面有自己提供的缓冲所以就没有进行处理。刚测试了一下,OnPaint里面如果完成绘图一次的操作大概需要15ms。里面画网格部分没有优化,全部采用所有线全部画一遍。

也可能,不是你重绘的问题,而是Form在画Panel的时候产生的闪烁。C#有个很不爽的地方是Form上的控件一多显示的时候就会闪烁。所以你可以首先试试把你这个重绘的做法单独做在一个Form上,然后用弹出框的方式弹出来看看是否会闪烁,如果不会那基本就能确定是因为那个Panel什么的问题而不是你这些重绘代码的问题了。相应的解决方案相信你也就有了。

感谢帮忙分析。目前测试情况为,将owner.AutoScrollPosition=pt;//owner为control的容器panelpanel的autoscroll属性为true上面这句话去掉之后就看不到闪烁的情况了。但是panel的滚动条都变为了0位置,不是我想要的居中效果。

嘿嘿,感觉有点奇怪,偷懒吧你。你重绘所有区域(会超出Panel的区域),然后利用Panel的AutoScrollPosition来调整显示区域。看起来确实蛮方便。正常来说应该确定好显示区域,然后重绘这个区域到Panel就是,不要再把调整丢给控件去做。
解决方案:
15ms是不会卡的。至少你感觉不到。除非你是不停的绘制。人的眼镜所所接受的一秒钟24帧。并不多40ms一帧。

时间: 2024-09-20 00:01:34

winform panel里面放了一个control,在control上绘图,放大时存在闪烁现象。的相关文章

编程-两个孩子,一个孩子将a b c d 4个球放入一个只有一端开放的细管子里

问题描述 两个孩子,一个孩子将a b c d 4个球放入一个只有一端开放的细管子里 两个孩子,一个孩子将a b c d 4个球放入一个只有一端开放的细管子里,另一个孩子摸球,编程计算第二个孩子摸出来球的顺序 解决方案 假设第2个孩子只能从最外面的球往里面摸,有2种可能的程序: 1.程序可设计输入4个数,分别为a,b,c,d放入管子的顺序,如 1,3,2,4表示先放a,然后是c,接着是b,最后是d,那么拿出的顺序则相反,可以通过数组的倒序, 或者堆栈等等方法求出顺序 2.程序认为放入顺序是不确定的

java 递归 输入一个ID 怎么把这个ID下所有的子ID 放入一个list里面 递归都写好了

问题描述 java 递归 输入一个ID 怎么把这个ID下所有的子ID 放入一个list里面 递归都写好了 HashMap> results = new HashMap>(); //输入的ID int ID=Integer.parseInt(Catid); //表中所有的数据 aas=cloudnewscategory.selectAllGory(); System.out.println("所有记录="+aas); for (CloudNewsCategory gory :

文字溢出实现溢出的部分再放入一个新生成的div中具体代码_javascript技巧

看到群里有人提了一个问题,说文字溢出,如何实现溢出的文字放入一个新生成的div中, 想了一下原理,就是判断是否能在div里放下,如果不能,则在应该断开的地方,差入到新的div中,代码如下: 复制代码 代码如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> &

httpwebrequest-C# winform程序用HttpWebRequest提交一个参数,需要服务端计算后返回结果

问题描述 C# winform程序用HttpWebRequest提交一个参数,需要服务端计算后返回结果 请求为 网址?param=XXX 我的服务器端改怎么写? 解决方案 HttpWebRequest有对应的HttpWebResponse,这个HttpWebResponse对象返回请求的页面的相应的所有信息字符串. 比如,你的请求url是"http://www.baidu.com/",那么HttpWebResponse对象返回的就应该是百度首页的html的所有字符.因此,如果你的请求页

我用winform给webserver发送了一个文件,我想让服务器在接收完文件后给客户端发送一个信息

问题描述 我用winform给webserver发送了一个文件,我想让服务器在接收完文件后给客户端发送一个信息 用c#做一个wimform客户端用webclient.uploadfile给服务器发送一个文件,在服务器接收完之后返回一个信息给客户端,首先我需要知道怎么给服务器发送一段字符串,比如"ok",在服务器收到OK之后表示文件接收完了,那么会给客户端返回一个信息,比如"over",然后客户端接收到这个信息.并用messagebox显示出来"over&q

用Winform开发了一个程序,界面上的控件在Win7下是基本对齐的,到了WindowsServer2008下就变的完全对不齐了?请问这是什么原因?

问题描述 用Winform开发了一个程序,界面上的控件在Win7下是基本对齐的,到了WindowsServer2008下就变的完全对不齐了?请问这是什么原因?RT 解决方案 解决方案二:不知道你是用什么方法"对齐"的,所以无法判断.比如说你用"空格"来搞什么"对齐",那么不同系统的同一个主题下的细节设置也是有调整的,空格在高版本的windows下肯定就变宽了一些,那么自然在高版本windows下就"鼓出去"了.你用于"

一个td里面放了一个文字,和一个combobox,我想取到既有文字,又对应combobox的值

问题描述 一个td里面放了一个文字,和一个combobox,我想取到既有文字,又对应combobox的值 解决方案 日期用label或者span容器扩起,然后获取容器的innerHTML属性值,combobox调用api来获取,easyui类似 $('#xxxx').combobox('getValue') #xxxx是input的id 解决方案二: 把枚举类型的值绑定到一个ComboBox中

winform-C# Winform 用进度条显示一个命令行命令的进度

问题描述 C# Winform 用进度条显示一个命令行命令的进度 如题,我想用7z.exe来解压ISO镜像文件,因为时间可能会比较长,所以需要一个进度条来显示一下,7z.exe在执行的时候会有一个不断刷新的百分比,(如图). 所以有兄弟知道怎么做这个命令行么?那个不断刷新的百分比应该有点用吧... 解决方案 用Console.Write((char)8); 可以输出退格.这样就可以不断刷新了. 解决方案二: 可以,参考:http://blog.csdn.net/hcj116/article/de

c#-C# 两个孩子,一个孩子将a b c d 4个球放入一个只有一端开放的细管子里

问题描述 C# 两个孩子,一个孩子将a b c d 4个球放入一个只有一端开放的细管子里 两个孩子,一个孩子将a b c d 4个球放入一个只有一端开放的细管子里 要求C# 解决方案 可以这个细管子看成一个栈(先进后出),然后再用代码实现这个栈,可以去看我刚刚写的博客:http://blog.csdn.net/android_s123/article/details/50393042