把wx的窗体绘图输出到位图

Wed 22 April 2009
  • 手艺 tags:
  • python
  • wx published: true comments: true

我想用这种低调的含糊不清的标题也没有什么坏处。

问题很简单,我们要把在wx窗体上绘制的图形保存到一个位图文件中去。

首先看一下wx的绘图机制,所有和绘图相关的操作,都从wx.DC这样一个父类继承。DC即Device Context,文档里对这个类的功能有这样的描述

A wx.DC is a device context onto which graphics and text can be drawn. It is intended to represent a number of output devices in a generic way, so a window can have a device context associated with it, and a printer also has a device context. In this way, the same piece of code may write to a number of different devices, if the device context is used as a parameter.
进而,这样的DC包括子类WindowDC,PrinterDC等等,用于在不同的设备上画图。WindowDC又有两个子类ClientDC和MemoryDC。在窗体上画图,就是在EVT_PAINT事件里,应该使用ClientDC的子类PaintDC。而MemoryDC就是在内存中的位图上绘图。要把窗体上的图形输出到位图文件中去,只要把PaintDC中的绘制的图形数据拷贝到MemoryDC上就可以了。

以下是一个典型的OnPaint方法
[codesyntax lang="python" lines="fancy"]
class CanvasAlpha(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent, -1)
self.SetBackgroundColour(wx.Color(255, 255, 255))
self.Bind(wx.EVT_PAINT, self.OnPaint)

def OnPaint(self, evt):
dc = wx.PaintDC(self)
gc = wx.GraphicsContext.Create(dc)

## draw ...
[/codesyntax]
在拷贝之前,首先创建一个新的位图并且指定他的宽高
bitmap = wx.EmptyBitmap(width, height, -1)
获得memoryDC
memDC = wx.MemoryDC()
指定memoryDC的内存对象
memDC.SelectObject(bitmap)
利用DC中一个非常重要的Blit方法,把PaintDC上的图形轻松地拷贝到MemoryDC上(关于参数的意义请参考wx的文档了)
memDC.Blit(0, 0, width, height, dc, 0, 0)
这还没有完,将memoryDC的内存对象设置为null,即传入一个null对象。这一步相当于flush。
memDC.SelectObject(wx.NullBitmap)
最后,用bitmap的Save方法就可以非常轻松地输出图片了
bitmap.SaveFile(filename, wx.BITMAP_TYPE_JPEG)

这样,在窗口中截图也就实现了。