Reputation: 1
In my program I have an image (bitmap) loaded into a wxScrolledWindow. I'm trying to draw a grid over the image but I just cannot get it to work. My job is to port this program over from Windows, which it was originally developed on, and make it work on Mac as well but it is a bigger pain the butt than I expected.
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 )
This code works just fine on Windows 7, but I keep getting this error when running it on 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 is a wxStaticBitmap, and self.wxBitmap is the same exact image. My guess is it has something to do with a GraphicsContext, perhaps? There was a similar question asked here: How to send PaintEvent in wxpython but this did not help me. I did what they suggested with self.Refresh() but I have the same error coming up. Why would this be working on Windows but not on Mac? No drawing seems to be occurring on the image.
Upvotes: 0
Views: 565
Reputation: 6306
First, you shouldn't be handling the paint event for a native widget. Sometimes it will work, like this case on Win7, but other times it won't, and it is not officialy supported by wxWidgets. (The behavior is "undefined")
Second, why bother painting the wx.StaticBitmap
at all? If you need to change the bitmap that the widget is displaying you can just give it a new one with its SetBitmap
method. In this case if the grid you are drawing is dynamic (needs to change over time) then you could use a wx.MemoryDC
to make a new bitmap with the grid (IOW, draw the bitmap and call drawGrid
on the memory DC) and then pass that new bitmap to SetBitmap
.
Third, you don't usually see calls to event.Skip
in paint event handlers. There may be cases where this could cause problems too, unless the base classes are expecting it.
Forth, it's not really a problem but using wx.BufferedPaintDC
on Mac is superfluous as the platform is already double-buffering everything. GTK does so in most cases as well. There is a wx.AutoBufferedPaintDC
that will either be a PaintDC
or a BufferedPaintDC
depending on if buffering is needed or not for the given platform. Or you can decide which to use in your own code by looking at the return value of window.IsDoubleBuffered()
.
Finally, if you would rather handle this problem using paint events instead of generating and swapping images in the wx.StaticBitmap
then another approach you could take is to make a custom class similar to wx.StaticBitmap
that simply paints a bitmap on itself, but also knows how to manage drawing the grid when it is needed, then you could use that class in place of the wx.StaticBitmap
. You could use the wx.lib.statbmp
module as a starting point.
Upvotes: 2