双缓冲类里的OnPaint与OnSize,以及构造函数的关系
代码摘自wx\lib\agw\knobctrl.py
一点体会是,OnSize作为class的函数,被放在构造函数里执行,会先于OnPaint执行。
测试结果是,初始启动后,会执行8次OnSize(为什么是8次?2个闹钟就2次,每个闹钟分别1次SetTags,其中一个调用一次self.OnTicks,总共应该是5次),然后才会执行2次OnPaint。
而且这两次OnPaint可能还是附送的,估计是执行的时候正好console盖住gui,gui恢复显示的时候会执行两次OnPaint
用任意窗口遮住OnPaint,然后最小化,就会发现执行两次OnPaint(为什么是两次?一次就够了啊)
每次OnPaint的时候,会自动调用OnSize为之准备好的数据:self._Buffer
#----------------------------------------------------------------------
# BUFFERENDWINDOW Class
# This Class Has Been Taken From The wxPython Wiki, And Slightly
# Adapted To Fill My Needs. See:
#
# http://wiki.wxpython.org/index.cgi/DoubleBufferedDrawing
#
# For More Info About DC And Double Buffered Drawing.
#---------------------------------------------------------------------- class BufferedWindow(wx.Window):
"""
A Buffered window class. To use it, subclass it and define a `Draw(dc)` method that takes a `dc`
to draw to. In that method, put the code needed to draw the picture
you want. The window will automatically be double buffered, and the
screen will be automatically updated when a Paint event is received. When the drawing needs to change, you app needs to call the
L{BufferedWindow.UpdateDrawing} method. Since the drawing is stored in a bitmap, you
can also save the drawing to file by calling the
`SaveToFile(self, file_name, file_type)` method.
""" def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.DefaultSize,
style=wx.NO_FULL_REPAINT_ON_RESIZE, agwStyle=KC_BUFFERED_DC):
"""
Default class constructor.
:param `style`: the window style;
:param `agwStyle`: if set to ``KC_BUFFERED_DC``, double-buffering will
be used.
""" wx.Window.__init__(self, parent, id, pos, size, style) self.Bind(wx.EVT_PAINT, self.OnPaint)
self.Bind(wx.EVT_SIZE, self.OnSize)
self.Bind(wx.EVT_ERASE_BACKGROUND, lambda x: None) # OnSize called to make sure the buffer is initialized.
# This might result in OnSize getting called twice on some
# platforms at initialization, but little harm done.
self.OnSize(None) def Draw(self, dc):
"""
This method should be overridden when sub-classed.
:param `dc`: an instance of `wx.DC`.
"""
pass def OnPaint(self, event): # 需要使用的时候,才会被系统自动调用,否则也不会执行到这里来
"""
Handles the ``wx.EVT_PAINT`` event for L{BufferedWindow}.
:param `event`: a `wx.PaintEvent` event to be processed.
"""
print "OnPaint"
# All that is needed here is to draw the buffer to screen
if self._agwStyle == KC_BUFFERED_DC: # 如果是双缓冲
dc = wx.BufferedPaintDC(self, self._Buffer) # 从已经准备好的双缓冲中直接得到DC指针并显示
else: # 如果不是双缓冲
dc = wx.PaintDC(self) # 那就直接申请新的PaintDC,无法从双缓冲处直接获得DC
dc.DrawBitmap(self._Buffer,0,0) # 也可以用新的DC读取相关数据,现场读数据也许慢,且很多数据的话会闪烁? def OnSize(self,event):
"""
Handles the ``wx.EVT_SIZE`` event for L{BufferedWindow}.
:param `event`: a `wx.SizeEvent` event to be processed.
""" # The Buffer init is done here, to make sure the buffer is always
# the same size as the Window
self.Width, self.Height = self.GetClientSizeTuple()
print "OnSize" # Make new off screen bitmap: this bitmap will always have the
# current drawing in it, so it can be used to save the image to
# a file, or whatever. # This seems required on MacOS, it doesn't like wx.EmptyBitmap with
# size = (0, 0)
# Thanks to Gerard Grazzini if "__WXMAC__" in wx.Platform:
if self.Width == 0:
self.Width = 1
if self.Height == 0:
self.Height = 1 self._Buffer = wx.EmptyBitmap(self.Width, self.Height) # 准备空图片(以后会被子类的数据所填充) memory = wx.MemoryDC() # 在内存DC里建立图像。经测试,发现这个memory局部变量是用来覆盖闹钟的背景色的,因为与Form的颜色一致,所以闹钟的效果被单独突出显示来了。
memory.SelectObject(self._Buffer) # DC连接要显示的图像
memory.SetBackground(wx.Brush(self.GetBackgroundColour())) # 设置图像背景,并使用刷子刷干净
memory.SetPen(wx.TRANSPARENT_PEN) # 选中透明画笔
memory.Clear() # 清空背景图 minradius = min(0.9*self.Width/2, 0.9*self.Height/2)
memory.DrawCircle(self.Width/2, self.Height/2, minradius) # (使用透明铅笔)画圆
memory.SelectObject(wx.NullBitmap) # 选中空图像,其实这句话我不明白,经过测试,去掉这句话不影响,是用来丢弃数据或者回收垃圾的。且这里的Memory似乎也不会被传递出去。
self._region = wx.RegionFromBitmapColour(self._Buffer, self.GetBackgroundColour()) # 使用背景色模板,除去背景色以后,得到一张透明图
self._minradius = minradius self.UpdateDrawing() def UpdateDrawing(self):
"""
This would get called if the drawing needed to change, for whatever reason.
The idea here is that the drawing is based on some data generated
elsewhere in the system. If that data changes, the drawing needs to
be updated.
""" if self._agwStyle == KC_BUFFERED_DC:
dc = wx.BufferedDC(wx.ClientDC(self), self._Buffer) # 每次都建立新的双缓冲DC,以后好直接在OnPaint里改变DC指针即可
self.Draw(dc) # 调用子类的Draw,这时候可以填充相关数据
else:
# update the buffer
dc = wx.MemoryDC() # 申请内存DC,虽然也是单独准备DC,但毕竟不是系统提供的双缓冲
dc.SelectObject(self._Buffer) # 似乎这里的DC选中数据也没有用,这个DC不会被传递到OnPaint里去悠悠什么用?而且这里不是self.dc self.Draw(dc)
# update the screen
wx.ClientDC(self).Blit(0, 0, self.Width, self.Height, dc, 0, 0)
双缓冲类里的OnPaint与OnSize,以及构造函数的关系的更多相关文章
- C# GDI+双缓冲技术
我想有很多搞图形方面的朋友都会用到双缓冲技术的时候,而且有的时候她的确是个头疼的问题.最近我也要用双缓冲技术,程序怎么调试都不合适,当要对图形进行移动时,总是会出现闪烁抖动.在网上找了些资料,说得都不 ...
- C++零食:WTL中使用双缓冲避免闪烁
双缓冲的原理可以这样形象的理解:把电脑屏幕看作一块黑板.首先我们在内存环境中建立一个"虚拟"的黑板,然后在这块黑板上绘制复杂的图形,等图形全部绘制完毕的时候,再一次性的把内存中绘制 ...
- Duilib的双缓冲实现,附带GDI、WTL的双缓冲实现
前言: 闪烁问题,之前的经验是使用双缓冲,借此机会,把双缓冲的研究心得总结下. 双缓冲的含义: 缓冲这个词,相信大家都不陌生,Cache.主要是为了解决上下游(或者模块.或者系统)等性能不匹配问题.如 ...
- MFC双缓冲绘图(2015.09.24)
问题引入: 最近在尝试编写贪吃蛇游戏时遇到这么一个问题:当系统以较快频率向窗口发送WM_PAINT消息时,调用OnPaint()函数在窗口中绘制图形就会发生闪烁现象. 问题分析: 当我们把绘图过程放在 ...
- win32下的双缓冲绘图技术
一:双缓冲原理 为了解决窗口刷新频率过快所带来的闪烁问题,利用双缓冲技术进行绘图.所谓双缓冲技术,就是将资源加载到内存,然后复制内存数据到设备DC(这个比较快),避免了直接在设备DC上绘图(这个比较慢 ...
- C#绘图双缓冲
C#绘图双缓冲 C#双缓冲解释: 简单说就是当我们在进行画图操作时,系统并不是直接把内容呈现到屏幕上,而是先在内存中保存,然后一次性把结果输出来,如果没用双缓冲的话,你会发现在画图过程中屏幕会闪的很厉 ...
- C#-gdi绘图,双缓冲绘图,Paint事件的触发
一. 画面闪烁问题与双缓冲技术 1.1 导致画面闪烁的关键原因分析: 1 绘制窗口由于大小位置状态改变进行重绘操作时 绘图窗口内容或大小每改变一次,都要调用Paint事件进行重绘操作,该操作会使画面 ...
- 《MFC游戏开发》笔记六 图像双缓冲技术:实现一个流畅的动画
本系列文章由七十一雾央编写,转载请注明出处. http://blog.csdn.net/u011371356/article/details/9334121 作者:七十一雾央 新浪微博:http:/ ...
- VC 绘图,使用双缓冲技术实现
VC 绘图,使用双缓冲技术实现 - Cloud-Datacenter-Renewable Energy-Big Data-Model - 博客频道 - CSDN.NET VC 绘图,使用双缓冲技术实现 ...
随机推荐
- Autolayout 03
Debugging in Code 有两个调试layout问题的阶段. 1. Map from “this view is in the wrong place” to “this constrain ...
- 【spring boot】10.spring boot下的单元测试
spring boot下的单元测试,思前想后还是需要单独用一章篇幅来看看. 然后在看了介绍和使用时候,我感觉并不想多去看了. 但是还是给后来人留下参考的路径: 官网说明:https://spring. ...
- 安全 -- mysql参数化查询,防止Mysql注入
参数化查询(Parameterized Query 或 Parameterized Statement)是指在设计与数据库链接并访问数据时,在需要填入数值或数据的地方,使用参数(Parameter) ...
- java关于Timer schedule执行定时任务 1、在应用开发中,经常需要一些周期性的操作,比如每5分钟执行某一操作等
1.在应用开发中,经常需要一些周期性的操作,比如每5分钟执行某一操作等.对于这样的操作最方便.高效的实现方式就是使用java.util.Timer工具类. private java.util.Time ...
- > 1366 - Incorrect string value: '\xE6\xB5\x8B\xE8\xAF\x95...' for column 'description' at row 1 字符串格式错误
mysql 执行insert时报错 > 1366 - Incorrect string value: '\xE6\xB5\x8B\xE8\xAF\x95...' for column 'desc ...
- LeetCode Subsets I& II——递归
I Given a set of distinct integers, S, return all possible subsets. Note: Elements in a subset must ...
- (四)DOM对象和jQuery对象
学习jQuery,需要搞清楚DOM对象和jQuery对象的关系与区别,因为两者的方法并不共用,如果搞不清楚对象类型就会导致调用错误的方法. DOM(Document Object Model)称为文档 ...
- PHP增加$_ENV变量
在日常开发过程中,我们常常会将一些系统或模块配写在配置文件里.这样便于程序维护与修改.通常的配置文件有.ini , .xml等.配置文件的好处在于:1,便于管理.2,可读性高.但是,使用配置文件也会有 ...
- HDMI原理图信号PIN脚
HDMI(19Pin)/DVI(16 pin)的功能是热插拔检测(HPD),这个信号将作为主机系统是否对HDMI/DVI是否发送TMDS信号的依据.HPD是从显示器输出送往计算机主机的一个检测信号.热 ...
- Spring学习三----------注入方式
© 版权声明:本文为博主原创文章,转载请注明出处 Spring注入方式 本篇博客只讲最常用的两种注入方式:设值注入和构造器注入.代码为完整代码,复制即可使用. 1.目录结构 2.pom.xml < ...