wxPython中Mac OSX 10.8.5上的Paint Event问题

时间:2015-01-26 18:58:23

标签: python macos wxpython paint paintevent

在我的程序中,我将一个图像(位图)加载到wxScrolledWindow中。我试图在图像上画一个网格,但我无法让它工作。我的工作是将这个程序移植到它最初开发的Windows上,并使它在Mac上运行,但它比我预期的更大的痛苦。

def OnPaint(self, event):
    dc = wx.BufferedPaintDC(self.staticBitmap,self.staticBitmap.GetBitmap())
    dc.Clear()
    dc.DrawBitmap(self.wxBitmap, 0, 0)    
    self.drawGrid(dc)
    event.Skip()

def drawGrid(self, dc):
    gridWid, gridHgt = self.staticBitmap.GetBitmap().GetSize()
    numRows, numCols = self.gridSize, self.gridSize
    if self.controlPanel.showGridBox.IsChecked():
        dc.SetPen(wx.Pen(self.gridColor, self.gridThickness))
        dc.SetTextForeground(self.gridColor)
        cellWid = float( gridWid - 1) / numRows
        cellHgt = float( gridHgt - 1) / numCols
        for rowNum in xrange( numRows + 1) :
            dc.DrawLine( 0, rowNum*cellHgt, gridWid, rowNum*cellHgt )
        for colNum in xrange( numCols + 1 ) :
            dc.DrawLine( colNum*cellWid, 0, colNum*cellWid, gridHgt )

此代码在Windows 7上运行正常,但在Mac上运行时我一直收到此错误:

Traceback (most recent call last):
File "/Users/kyra/Documents/workspace/ADAPT/src/GUI.py", line 1617, in OnPaint
dc = wx.BufferedPaintDC(self.staticBitmap, self.staticBitmap.GetBitmap())
File "/usr/local/lib/wxPython-3.0.2.0/lib/python2.7/site-packages/wx-3.0-osx_cocoa/wx/_gdi.py", line 5290, in __init__
_gdi_.BufferedPaintDC_swiginit(self,_gdi_.new_BufferedPaintDC(*args, **kwargs))
wx._core.PyAssertionError: C++ assertion "window->MacGetCGContextRef() != NULL" failed at /BUILD/wxPython-src-3.0.2.0/src/osx/carbon/dcclient.cpp(195) in wxPaintDCImpl(): using wxPaintDC without being in a native paint event

self.staticBitmap是一个wxStaticBitmap,self.wxBitmap是完全相同的图像。我的猜测是它与GraphicsContext有关,也许呢?这里有一个类似的问题:How to send PaintEvent in wxpython但这对我没有帮助。我用self.Refresh()做了他们的建议,但是我遇到了同样的错误。为什么这会在Windows上运行而不在Mac上运行?图像上似乎没有绘图。

1 个答案:

答案 0 :(得分:2)

首先,您不应该处理本机窗口小部件的paint事件。有时它会起作用,就像在Win7上的这种情况一样,但有时它不会,并且它不受wxWidgets的官方支持。 (行为是“未定义的”)

其次,为什么要费心去绘wx.StaticBitmap?如果您需要更改窗口小部件正在显示的位图,您可以使用其SetBitmap方法为其添加新位图。在这种情况下,如果您绘制的网格是动态的(需要随时间变化),那么您可以使用wx.MemoryDC使用网格创建新的位图(IOW,绘制位图并调用drawGrid内存DC)然后将新位图传递给SetBitmap

第三,您通常不会在绘制事件处理程序中看到对event.Skip的调用。在某些情况下,这可能会导致问题,除非基类期待它。

第四,这不是一个真正的问题,但在Mac上使用wx.BufferedPaintDC是多余的,因为该平台已经对所有内容进行了双重缓冲。 GTK在大多数情况下都这样做。有一个wx.AutoBufferedPaintDC将是PaintDCBufferedPaintDC,具体取决于是否需要对给定平台进行缓冲。或者,您可以通过查看window.IsDoubleBuffered()的返回值来决定在自己的代码中使用哪个。

最后,如果您更愿意使用绘制事件而不是在wx.StaticBitmap中生成和交换图像来处理此问题,那么您可以采用的另一种方法是创建一个类似于wx.StaticBitmap的自定义类,它只是简单地绘制一个位图本身,但也知道如何在需要时管理绘制网格,然后你可以使用该类代替wx.StaticBitmap。您可以使用wx.lib.statbmp模块作为起点。