Search code examples
pythonbitmapbackgroundwxpython

wxPython - GC.DrawText removes background bitmap


I'm trying to draw a text on existing bitmap, but when I use the Graphics Context's DrawText method, the background is removed. But this happens only when I create background image from empty bitmap (using DrawText on Bitmap from loaded image works well). I think that the issue happens because I'm using MemoryDC to create an empty bitmap, but I'm quite new to wxPython, so I have no idea how to fix it.

Here's what I've done so far:

import wx

def GetEmptyBitmap(w, h, color=(0,0,0)):
    """
    Create monochromatic bitmap with desired background color.
    Default is black
    """
    b = wx.EmptyBitmap(w, h)
    dc = wx.MemoryDC(b)
    dc.SetBrush(wx.Brush(color))
    dc.DrawRectangle(0, 0, w, h)
    return b

def drawTextOverBitmap(bitmap, text='', fontcolor=(255, 255, 255)):
    """
    Places text on the center of bitmap and returns modified bitmap.
    Fontcolor can be set as well (white default)
    """
    dc = wx.MemoryDC(bitmap)
    gc = wx.GraphicsContext.Create(dc)
    font = wx.Font(16, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL)
    gc.SetFont(font, fontcolor)
    w,h = dc.GetSize()
    tw, th = dc.GetTextExtent(text)    
    gc.DrawText(text, (w - tw) / 2, (h - th) / 2)
    return bitmap

app = wx.App()
bmp_from_img =  bmp = wx.Image(location).Rescale(200, 100).ConvertToBitmap()
bmp_from_img = drawTextOverBitmap(bmp_from_img, "From Image", (255,255,255))

bmp_from_empty =  GetEmptyBitmap(200, 100, (255,0,0))
bmp_from_empty = drawTextOverBitmap(bmp_from_empty, "From Empty", (255,255,255))


frame = wx.Frame(None)
st1 = wx.StaticBitmap(frame, -1, bmp_from_img, (0,0), (200,100))
st2 = wx.StaticBitmap(frame, -1, bmp_from_empty, (0, 100), (200, 100))
frame.Show()
app.MainLoop()

As I said, the StaticBitmap which uses the loaded image is displayed correctly, but the one created with EmptyBitmap has no background.

Do you have any ideas how to make it work?

Thank you


Solution

  • This seems like a bug to me. Use the following to make it work:

    def GetEmptyBitmap(w, h, color=(0,0,0)):
        # ...
        # instead of
        # b = wx.EmptyBitmap(w, h)
        # use the following:
        img = wx.EmptyImage(w, h)
        b = img.ConvertFromBitmap()
        # ...
    

    I think not the wx.MemoryDC is to blame, but the platform-specific bitmap creation routines, where there is more going on under the hood. By starting off with a wx.Image the output seems to be more predictable/useful.