在我的程序中,我将一个图像(位图)加载到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上运行?图像上似乎没有绘图。
答案 0 :(得分:2)
首先,您不应该处理本机窗口小部件的paint事件。有时它会起作用,就像在Win7上的这种情况一样,但有时它不会,并且它不受wxWidgets的官方支持。 (行为是“未定义的”)
其次,为什么要费心去绘wx.StaticBitmap
?如果您需要更改窗口小部件正在显示的位图,您可以使用其SetBitmap
方法为其添加新位图。在这种情况下,如果您绘制的网格是动态的(需要随时间变化),那么您可以使用wx.MemoryDC
使用网格创建新的位图(IOW,绘制位图并调用drawGrid
内存DC)然后将新位图传递给SetBitmap
。
第三,您通常不会在绘制事件处理程序中看到对event.Skip
的调用。在某些情况下,这可能会导致问题,除非基类期待它。
第四,这不是一个真正的问题,但在Mac上使用wx.BufferedPaintDC
是多余的,因为该平台已经对所有内容进行了双重缓冲。 GTK在大多数情况下都这样做。有一个wx.AutoBufferedPaintDC
将是PaintDC
或BufferedPaintDC
,具体取决于是否需要对给定平台进行缓冲。或者,您可以通过查看window.IsDoubleBuffered()
的返回值来决定在自己的代码中使用哪个。
最后,如果您更愿意使用绘制事件而不是在wx.StaticBitmap
中生成和交换图像来处理此问题,那么您可以采用的另一种方法是创建一个类似于wx.StaticBitmap
的自定义类,它只是简单地绘制一个位图本身,但也知道如何在需要时管理绘制网格,然后你可以使用该类代替wx.StaticBitmap
。您可以使用wx.lib.statbmp
模块作为起点。