I am stuck with the problem of generating bitmaps with alpha easily. I
want to generate bitmaps with alpha/mask. I want antialiased drawing.
The problem is to let the background shine through properly.
Using wx.GCDC for painting is too slow using it in a wx.PaintDC (too
many elements). I used a GraphicsContext on a MemoryDC instead.
I need to perform the following steps:
1) generate the wx.Bitmap (see createarrow). This generates a BMP with
a yellow, bordered triangle which has the outer pixels not set
(wx.TRANSPARENT_BRUSH). When you look at it in e.g. GIMP, the
checkered background shows through, so it seems to have 'holes' in it
(but no alpha channel).
2) Create another bitmap for a wx.StaticBitmap. On this bitmap all
sorts of pre-generated bitmaps are stacked atop (two yellow triangles
in this example).
This leads to my problem: When you run the attached sample, in the
lines
dc.DrawBitmap(subbmp, 10, 1, True)
dc.DrawBitmap(subbmp, 20, 1, True)
the green background shows through around the stacked arrow instead
the bitmap, which has been drawn first. Also the
dc.DrawRectangle(0, 0, self.statbmpwidth, self.statbmpheight)
seems to have no effect?
My question:
How to properly generate in-memory-bitmaps *with* smooth drawing which
can be stacked showing the underlying bitmaps where there are 'holes'?
With best regards,
# -*- coding: utf-8 -*-
# tested on wxPython 2.8.12./Win7
import wx
class testframe(wx.Frame):
def __init__(self, *args, **kwds):
wx.Frame.__init__(self, *args, **kwds)
pnl = wx.Panel(self, -1)
self.pnl = pnl
pnl.SetBackgroundColour(wx.GREEN)
self.statbmpheight = 32
self.statbmpwidth = 128
self.initbmp()
sz = wx.BoxSizer(wx.VERTICAL)
sz.Add(self.statbmpm, 0, wx.EXPAND|wx.ALL, 0)
sz.Add((1,1), 1, wx.EXPAND|wx.ALL, 4)
szmain = wx.BoxSizer(wx.HORIZONTAL)
szmain.Add(sz, 1, wx.EXPAND, 0)
szmain.Add((1,1), 1, wx.EXPAND, 0)
pnl.SetSizer(szmain)
szmain.Fit(self)
self.Bind(wx.EVT_SIZE, self.onsize)
def initbmp(self):
self.arrow = self.createarrow()
bmp = wx.EmptyBitmap(self.statbmpwidth, self.statbmpheight)
self.paintonbmp(bmp, self.arrow)
self.statbmpm = wx.StaticBitmap(self.pnl, -1, bmp)
self.SetMinSize((self.statbmpwidth + 16, self.statbmpheight +
10))
def paintonbmp(self, bmp, subbmp):
dc = wx.MemoryDC()
dc.SelectObject(bmp)
gc = wx.GraphicsContext.Create(dc)
systemgrey =
wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE)
dc.SetBrush(wx.Brush(systemgrey))
gc.SetBrush(wx.Brush(systemgrey))
dc.SetPen(wx.Pen(systemgrey))
dc.DrawRectangle(0, 0, self.statbmpwidth, self.statbmpheight)
dc.DrawBitmap(subbmp, 10, 1, True)
dc.DrawBitmap(subbmp, 20, 1, True)
dc.SelectObject(wx.NullBitmap)
def onsize(self, evt):
self.Refresh()
evt.Skip()
def createarrow(self):
bmp = wx.EmptyBitmap(22, 22)
dc = wx.MemoryDC()
dc.SelectObject(bmp)
gc = wx.GraphicsContext.Create(dc)
dc.Clear()
gc.SetBrush(wx.TRANSPARENT_BRUSH)
gc.DrawRectangle(0,0,32,32)
mypath = gc.CreatePath()
mypath.MoveToPoint(1, 11)
mypath.AddLineToPoint(21, 1)
mypath.AddLineToPoint(21, 21)
mypath.CloseSubpath()
gc.StrokePath(mypath)
gc.SetPen(wx.Pen('black', 2))
gc.SetBrush(wx.Brush('yellow'))
gc.StrokePath(mypath)
gc.FillPath(mypath)
dc.SelectObject(wx.NullBitmap)
bmp.SaveFile('arrow.bmp', wx.BITMAP_TYPE_BMP)
return bmp
if __name__ == '__main__':
app = wx.App(0)
frame1 = testframe(None, -1, 'mytestframe')
frame1.Show()
# import wx.lib.inspection as wxli
# wxli.InspectionTool().Show()
app.MainLoop()