Using wx.MemoryDC for drawing on bitmaps

I have an application where I need to keep three bitmaps on-hand, and show
one of them in part of the application's frame (the user can change which is
should using radio buttons). I've been doing this with three wx.Bitmap's
for the buffers, and an extra one for the buffer that is currently on
display. Mostly, it works fine. When changing one of the three bitmaps, I
use a wx.MemoryDC:

    dc = wx.MemoryDC()
    dc.SelectObject(buffers[0])
    dc.DrawBitmap(wx.BitmapFromImage(im), 0, 0, False)
    del(dc)

The problem is that I sometimes get "wxAssertFailure" errors, with a message
saying "Bitmap is selected in anothre wxMemoryDC, delete the first
wxMemoryDC or use SelectObject(NULL)". I can't find a way to do
dc.SelectObject(NULL) in wx.Python (using "None" does not work), so I use
del(dc). Should this be reliable enough, or do I need to force a garbage
collection pass to make sure it works? I may have some problems in the rest
of the code (maybe my threading logic is not quite right and I'm accidently
doing drawing from with another thread, for example), but currently my
suspicions are that the deletion is not freeing the device context
immediately. I've included my picture window class at the bottom of the
mail in case it is useful.

Many thanks for any hints.

David Brown
Norway

"Utvikling er kunsten av � vikle seg ut av det man har viklet seg inn i"

···

--

picCols = 512
picRows = 512

class PicWin(wx.Window) :
    def __init__(self, parent, ID) :
        wx.Window.__init__(self, parent, ID, style =
wx.NO_FULL_REPAINT_ON_RESIZE |
                           wx.SIMPLE_BORDER)
        wx.EVT_PAINT(self, self.OnPaint)
        self.SetSize((picCols, picRows))
        self.buffers = [None] * 3
        for i in range(3) :
            self.buffers[i] = wx.EmptyBitmap(picCols, picRows)
            dc = wx.BufferedDC(None, self.buffers[i])
            dc.SetBackground(wx.Brush(wx.WHITE))
            dc.Clear()
        self.buffer = wx.EmptyBitmap(picCols, picRows)
        dc = wx.BufferedDC(None, self.buffer)
        dc.SetBackground(wx.Brush(wx.WHITE))
        dc.Clear()
        self.currentBuf = bufRaw
        self.minX = 10
        self.maxX = 400
        self.minY = 50
        self.maxY = 500
        return

    def update(self, line) :
        dc = wx.BufferedDC(wx.ClientDC(self), self.buffer)
        dc.BeginDrawing()
        dc.DrawBitmap(self.buffers[self.currentBuf].GetSubBitmap(
                wx.Rect(0, line, 512, 1)), 0, line, False)
        self.refreshLines(dc)
        dc.EndDrawing()
        del dc
        return

    def changeBuffer(self, newBuff) :
        self.currentBuf = newBuff
        self.refreshBuffer()
        return

    def refreshBuffer(self) :
        dc = wx.BufferedDC(wx.ClientDC(self), self.buffer)
        dc.BeginDrawing()
        dc.DrawBitmap(self.buffers[self.currentBuf], 0, 0, False)
        self.refreshLines(dc)
        dc.EndDrawing()
        del dc
        return

    def refreshLines(self, dc) :
        dc.SetPen(wx.Pen(wx.BLUE))
        dc.DrawLine(self.minX, 0, self.minX, picRows)
        dc.DrawLine(self.maxX, 0, self.maxX, picRows)
        dc.DrawLine(0, self.minY, picCols, self.minY)
        dc.DrawLine(0, self.maxY, picCols, self.maxY)
        return

    def OnPaint(self, event) :
        dc = wx.BufferedPaintDC(self, self.buffer)
        return

To select a bitmap *out* of a wxMemoryDC, use:

dc.SelectObject(wxNullBitmap)

this will remove the existing bitmap from the DC, so freeing it for use
by other DCs.

Bryan

···

The problem is that I sometimes get "wxAssertFailure" errors, with a message
saying "Bitmap is selected in anothre wxMemoryDC, delete the first
wxMemoryDC or use SelectObject(NULL)". I can't find a way to do
dc.SelectObject(NULL) in wx.Python (using "None" does not work), so I use
del(dc). Should this be reliable enough, or do I need to force a garbage
collection pass to make sure it works? I may have some problems in the rest
of the code (maybe my threading logic is not quite right and I'm accidently
doing drawing from with another thread, for example), but currently my
suspicions are that the deletion is not freeing the device context
immediately. I've included my picture window class at the bottom of the
mail in case it is useful.

--
Bryan Cole
Teraview Ltd., 302-304 Cambridge Science Park, Milton Road, Cambridge CB4 0WG, United Kingdom.
tel: +44 (1223) 435380 / 435386 (direct-dial) fax: +44 (1223) 435382

"bryan cole" <bryan.cole@teraview.com> wrote in message
news:1068216749.19914.27.camel@bryan.teraviewhq.local...

To select a bitmap *out* of a wxMemoryDC, use:

dc.SelectObject(wxNullBitmap)

this will remove the existing bitmap from the DC, so freeing it for use
by other DCs.

Bryan

Thanks - that is what I was looking for.

David

>
> The problem is that I sometimes get "wxAssertFailure" errors, with a

message

> saying "Bitmap is selected in anothre wxMemoryDC, delete the first
> wxMemoryDC or use SelectObject(NULL)". I can't find a way to do
> dc.SelectObject(NULL) in wx.Python (using "None" does not work), so I

use

> del(dc). Should this be reliable enough, or do I need to force a

garbage

> collection pass to make sure it works? I may have some problems in the

rest

> of the code (maybe my threading logic is not quite right and I'm

accidently

> doing drawing from with another thread, for example), but currently my
> suspicions are that the deletion is not freeing the device context
> immediately. I've included my picture window class at the bottom of the
> mail in case it is useful.

--
Bryan Cole
Teraview Ltd., 302-304 Cambridge Science Park, Milton Road, Cambridge CB4

0WG, United Kingdom.

···

tel: +44 (1223) 435380 / 435386 (direct-dial) fax: +44 (1223) 435382