如何用c# winform GDI+ 的方式实现不闪烁的高速实时波形图?
目前我的思路是线程1循环将每一次得到的数据追加到数据队列的尾部,线程2循环的每次取队列的前100个数据,调用绘图函数之后让其中的头几个数据出队,然后sleep若干时间.绘...
目前我的思路是
线程1 循环将每一次得到的数据追加到数据队列的尾部,
线程2 循环的每次取队列的前100个数据,调用绘图函数之后让其中的头几个数据出队,然后sleep若干时间.
绘图函数的思路:双缓冲GDI+实现:
1创建一个和控件尺寸相同的bitmap
2利用GDI+以画线的方式连接100个数据点,从而得到一帧图像.
3绘制完成后指定picbox的image为该bitmap
实际的情况是线程2的sleep如果比较小的话 画面闪烁非常厉害,而且cpu占用率高.
还望各位高手指点迷津. 展开
线程1 循环将每一次得到的数据追加到数据队列的尾部,
线程2 循环的每次取队列的前100个数据,调用绘图函数之后让其中的头几个数据出队,然后sleep若干时间.
绘图函数的思路:双缓冲GDI+实现:
1创建一个和控件尺寸相同的bitmap
2利用GDI+以画线的方式连接100个数据点,从而得到一帧图像.
3绘制完成后指定picbox的image为该bitmap
实际的情况是线程2的sleep如果比较小的话 画面闪烁非常厉害,而且cpu占用率高.
还望各位高手指点迷津. 展开
1个回答
展开全部
实现方法没问题,解决闪烁我知道的就两个办法
双缓冲
this.SetStyle(ControlStyles.DoubleBuffer | ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint, true);
this.UpdateStyles();
还有就是局部刷新
Rectangle rect = new Rectangle(new Point(0,0),new Size(50,50));
this.Invalidate(rect);
这两句可以加在属性里,表明只是刷新从坐标(0,0)开始的大小为50,50的区域
不过感觉数据每次都是变化的,,这样做,可能之前画的波形不会被覆盖.
尽可能的缩小波形图的大小,并且延长sleep间隔
比如系统里的进程管理器,迅雷的流量监视,他们的间隔都是1秒.
这对一般用户就已经可以接受了.
双缓冲
this.SetStyle(ControlStyles.DoubleBuffer | ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint, true);
this.UpdateStyles();
还有就是局部刷新
Rectangle rect = new Rectangle(new Point(0,0),new Size(50,50));
this.Invalidate(rect);
这两句可以加在属性里,表明只是刷新从坐标(0,0)开始的大小为50,50的区域
不过感觉数据每次都是变化的,,这样做,可能之前画的波形不会被覆盖.
尽可能的缩小波形图的大小,并且延长sleep间隔
比如系统里的进程管理器,迅雷的流量监视,他们的间隔都是1秒.
这对一般用户就已经可以接受了.
追问
我这个东西是用来检测心率的.曲线的变化速度很快.显然不是像迅雷那么简单,
现在我通过在onpaint里画图并双缓冲的形式往picbox里送图像,另一个接收和处理数据并加入到数据队列的方式基本上解决了闪烁的问题了.但是由于绘制曲线图的频率非常快,会造成cpu占用率过高的情况.正在想办法解决.你所说的那些在常规的慢速绘图的情况下当然没有问题.但是你试试一秒钟让你绘个30帧以上就明白我的难处了.
追答
归根结底,闪烁的原因是由于两帖之间图像差距大而引起的大范围重绘引起的.而且如果刷新与数据不同步,闪烁会越频繁.
有关图像闪烁,我也是上次在做一个图像缩放移动的窗体时候用到的.
看看下边这个链接,这跟我之前看过的一个解决方法差不多,都是在重绘上做调整.试试管不管用.
http://hi.baidu.com/liaomingsen/blog/item/db80c03592a5c287a71e124e.html
现在电脑上没装vs,没办法测试这些东西.
不过我感觉,关键还是在于怎么确定要刷新的区域和要更新的区域,然后重绘
刚才有想到一个想法,如果是波形图,肯定是朝着某一个方向递增或者延伸的图形.
可能有办法以移动图像的方式减少闪烁呢,不知道可否行的通.
可以百度HI聊
本回答被提问者采纳
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询