0

在我的程序中,我将图像(位图)加载到 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 上运行?图像上似乎没有绘图。

4

1 回答 1

2

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

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

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

第四,这不是一个真正的问题,但wx.BufferedPaintDC在 Mac 上使用是多余的,因为该平台已经对所有内容进行了双缓冲。GTK 在大多数情况下也是如此。根据给定平台是否需要缓冲,有一个wx.AutoBufferedPaintDC是 aPaintDC还是 a 。BufferedPaintDC或者您可以通过查看window.IsDoubleBuffered().

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

于 2015-01-27T17:29:19.960 回答