【问题标题】:Issue with Paint Event on Mac OSX 10.8.5 in wxPythonwxPython 中 Mac OSX 10.8.5 上的 Paint 事件问题
【发布时间】:2015-01-26 18:58:23
【问题描述】:

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

【问题讨论】:

标签: python macos wxpython paint paintevent


【解决方案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 模块作为起点。

【讨论】:

  • 谢谢。我想我之前的实习生很辛苦地进行了绘画活动,我只需要重新编写这些代码部分。所以小部件应该能够自己处理绘制事件,我什至不再需要 OnPaint() 方法,只需加载位图,创建 MemoryDC,然后调用 drawGrid() 就可以了吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-20
  • 2014-04-09
  • 2012-08-26
  • 1970-01-01
  • 1970-01-01
  • 2016-01-31
  • 1970-01-01
相关资源
最近更新 更多