2015-01-26 46 views
0

这让我的智慧结束了。我对wxPython相对比较陌生,而且我正在编辑别人的代码,所以请随身携带。 在我的程序中,我有一个图像(位图)加载到一个wxScrolledWindow。我试图在图像上绘制一个网格,但我无法实现它的工作。我的工作是将这个程序从Windows上移植过来,它最初是在Windows上开发的,并且使它可以在Mac上工作,但这比我预期的要更加痛苦。wxPython中的Mac OSX 10.8.5上的Paint Event问题

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

您可能希望将其发布到https://groups.google.com/forum/#!forum/wxpython-users组或https://groups.google.com/forum/#!forum/wxpython-mac – 2015-01-26 20:54:37

+0

谢谢,贴在那里以及:) – Kyra 2015-01-27 17:06:48

回答

1

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

二,为什么还要画根本wx.StaticBitmap?如果您需要更改小部件显示的位图,则可以使用其SetBitmap方法给它一个新的位图。在这种情况下,如果您正在绘制的网格是动态的(需要随时间变化),那么您可以使用wx.MemoryDC来创建一个带有网格的新位图(IOW,绘制位图并在内存DC上调用drawGrid),然后通过新的位图为SetBitmap

第三,您通常不会在绘画事件处理程序中看到对event.Skip的调用。有些情况下,这可能会导致问题,除非基类期望它。第一,这不是一个真正的问题,但在Mac上使用wx.BufferedPaintDC是多余的,因为平台已经对所有东西进行了双缓冲。 GTK在大多数情况下也是如此。有一个wx.AutoBufferedPaintDC,它可以是PaintDCBufferedPaintDC,具体取决于给定平台是否需要缓冲。或者您可以通过查看返回值window.IsDoubleBuffered()来决定在自己的代码中使用哪一个。

最后,如果你使用的油漆事件,而不是产生,并在wx.StaticBitmap那么你可以采取另一种方法是交换图像做出类似wx.StaticBitmap自定义类,简单地画上自身的位图,而解决这个问题,但也知道如何在需要时管理绘制网格,然后您可以使用该类代替wx.StaticBitmap。您可以使用wx.lib.statbmp模块作为起点。

+0

谢谢。我想在我之前的实习生以艰难的方式去描述绘画事件,而我只需要重写那些代码部分。所以这个小部件应该能够自己处理绘画事件,我甚至不需要OnPaint()方法,只需加载位图,创建一个MemoryDC,然后调用drawGrid()就可以了? – Kyra 2015-01-27 18:10:46