Blit bitmaps on top of another

Hello. I need some help with device context. I’m using GraphicsContext right now and basically I want to do this:

I have a background where I want to create and draw objects

Every object have different shape which are calculated once and I want to save this shape into a bitmap so I can draw

at the different positions on the screen. So the main task is:

  • Having a background

  • Blit a lot of bitmaps to it.

In the end I should also perform moving every shape on the screen, scaling it etc.

Here is the full demo:

import wx

class FrameCanvas(wx.ScrolledWindow):

def __init__(self, parent, id = -1, size = wx.DefaultSize):
    wx.ScrolledWindow.__init__(self, parent, id, (0, 0), size=size, style=wx.SUNKEN_BORDER)
   
    self.parent     = parent
    self.maxWidth   = 1200
    self.maxHeight  = 800
   
    self.SetBackgroundColour("RED")
    self.SetCursor(wx.StockCursor(wx.CURSOR_PENCIL))

    self.SetVirtualSize((self.maxWidth, self.maxHeight))
    self.SetScrollRate(20,20)

    self.buffer  = wx.EmptyBitmap(self.maxWidth, self.maxHeight)
    self.buffer2 = wx.EmptyBitmap(self.maxWidth, self.maxHeight)

    self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftButtonEvent)
    self.Bind(wx.EVT_PAINT, self.OnPaint)
    self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnErase)

def OnPaint(self, event):

    dc = wx.BufferedPaintDC(self, self.buffer, wx.BUFFER_VIRTUAL_AREA)

   

def OnErase(self, event):
    pass

def OnLeftButtonEvent(self, event):
   
    dc   = wx.BufferedDC(None, self.buffer)
    gcdc = wx.GCDC(dc)
    gc   = gcdc.GetGraphicsContext()
 
    gcdc.SetBackground(wx.Brush(wx.Colour(230, 230, 230, 255)))
    gcdc.Clear()

    gc.SetBrush(wx.Brush(wx.Colour(200, 233, 240, 100)))
    gc.DrawRoundedRectangle(50, 50, 300, 300, 10)

   
    dc   = wx.BufferedDC(None, self.buffer2)
    gcdc = wx.GCDC(dc)
    gc   = gcdc.GetGraphicsContext()
 
    gcdc.SetBackground(wx.Brush(wx.Colour(0, 0, 0)))
    gcdc.Clear()

    gc.SetBrush(wx.Brush(wx.Colour(0, 255, 0, 100)))
    gc.DrawRoundedRectangle(100, 100, 300, 300, 100)

    dc   = wx.BufferedDC(None, self.buffer)
    gcdc = wx.GCDC(dc)
    gc   = gcdc.GetGraphicsContext()

    # if we put this line, we'll get rid of the black background so we
    # have shape on a transparent background, but it won't blend with it's first layer
    # because it's blended with the black background
···
    #

    self.buffer2.SetMaskColour((0,0,0))  

    gc.DrawBitmap(self.buffer2, 0, 0, self.maxWidth, self.maxHeight)

    self.Refresh()

if name == ‘main’:
app = wx.App(False)
frame = wx.Frame(None)
canvas = FrameCanvas(frame)
frame.Show()
app.MainLoop()

``

I want to do this:

I have a background where I want to create and draw objects

Every object have different shape which are calculated once and I want to save this shape into a bitmap so I can draw

at the different positions on the screen. So the main task is:

  • Having a background
  • Blit a lot of bitmaps to it.

I’ve had trouble with this with multiple tools – how to get something to draw anti-aliased against a transparent background, such that the anti-aliasing is done all in the alpha channel. Have you tried drawing on a transparent background?

But:

In the end I should also perform moving every shape on the screen, scaling it etc.

If you are going to scale anyway, you may well do fine re-drawing your shapes each time anyway – it’s likely to be fast enough, and will certainly look better than scaled bitmaps.

Take a look at wx.lib.floatcanvas – it can do a lot of this for you.

-Chris

···

On Aug 8, 2014, at 4:41 AM, Vladislav Cebotari cebotari.vladislav@gmail.com wrote:

Here is the full demo:

import wx

class FrameCanvas(wx.ScrolledWindow):

def __init__(self, parent, id = -1, size = wx.DefaultSize):

    wx.ScrolledWindow.__init__(self, parent, id, (0, 0), size=size, style=wx.SUNKEN_BORDER)

   
    self.parent     = parent

    self.maxWidth   = 1200

    self.maxHeight  = 800

   
    self.SetBackgroundColour("RED")

    self.SetCursor(wx.StockCursor(wx.CURSOR_PENCIL))



    self.SetVirtualSize((self.maxWidth, self.maxHeight))

    self.SetScrollRate(20,20)





    self.buffer  = wx.EmptyBitmap(self.maxWidth, self.maxHeight)

    self.buffer2 = wx.EmptyBitmap(self.maxWidth, self.maxHeight)









    self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftButtonEvent)

    self.Bind(wx.EVT_PAINT, self.OnPaint)

    self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnErase)





def OnPaint(self, event):



    dc = wx.BufferedPaintDC(self, self.buffer, wx.BUFFER_VIRTUAL_AREA)



   




def OnErase(self, event):

    pass


def OnLeftButtonEvent(self, event):

   
    dc   = wx.BufferedDC(None, self.buffer)

    gcdc = wx.GCDC(dc)

    gc   = gcdc.GetGraphicsContext()

 
    gcdc.SetBackground(wx.Brush(wx.Colour(230, 230, 230, 255)))

    gcdc.Clear()



    gc.SetBrush(wx.Brush(wx.Colour(200, 233, 240, 100)))

    gc.DrawRoundedRectangle(50, 50, 300, 300, 10)



   
    dc   = wx.BufferedDC(None, self.buffer2)

    gcdc = wx.GCDC(dc)

    gc   = gcdc.GetGraphicsContext()

 
    gcdc.SetBackground(wx.Brush(wx.Colour(0, 0, 0)))

    gcdc.Clear()



    gc.SetBrush(wx.Brush(wx.Colour(0, 255, 0, 100)))

    gc.DrawRoundedRectangle(100, 100, 300, 300, 100)



    dc   = wx.BufferedDC(None, self.buffer)

    gcdc = wx.GCDC(dc)

    gc   = gcdc.GetGraphicsContext()





    # if we put this line, we'll get rid of the black background so we
    # have shape on a transparent background, but it won't blend with it's first layer

    # because it's blended with the black background
    #



    self.buffer2.SetMaskColour((0,0,0))  



    gc.DrawBitmap(self.buffer2, 0, 0, self.maxWidth, self.maxHeight)







    self.Refresh()

if name == ‘main’:

app = wx.App(False)

frame = wx.Frame(None)

canvas = FrameCanvas(frame)

frame.Show()

app.MainLoop()

``

You received this message because you are subscribed to the Google Groups “wxPython-users” group.

To unsubscribe from this group and stop receiving emails from it, send an email to wxpython-users+unsubscribe@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

yes, I tried to draw on a transparent background( I tried to set a wx.TRANSPARENT_BRUSH and clear buffer with, and then I tried to clear with black color and set black as a mask color, then draw), each way didn’t work as expected. Yes, when changing one object I will redraw it, but for other which won’t change it will be much faster to blit for example 5 bitmaps than to for every objet draw a lot of lines and circles again.
Thank you for you response.

···

On Friday, 8 August 2014 18:03:00 UTC+3, Chris Barker - NOAA Federal wrote:

On Aug 8, 2014, at 4:41 AM, Vladislav Cebotari cebotari....@gmail.com wrote:

I want to do this:

I have a background where I want to create and draw objects

Every object have different shape which are calculated once and I want to save this shape into a bitmap so I can draw

at the different positions on the screen. So the main task is:

  • Having a background
  • Blit a lot of bitmaps to it.

I’ve had trouble with this with multiple tools – how to get something to draw anti-aliased against a transparent background, such that the anti-aliasing is done all in the alpha channel. Have you tried drawing on a transparent background?

But:

In the end I should also perform moving every shape on the screen, scaling it etc.

If you are going to scale anyway, you may well do fine re-drawing your shapes each time anyway – it’s likely to be fast enough, and will certainly look better than scaled bitmaps.

Take a look at wx.lib.floatcanvas – it can do a lot of this for you.

-Chris

Here is the full demo:

import wx

class FrameCanvas(wx.ScrolledWindow):

def __init__(self, parent, id = -1, size = wx.DefaultSize):

    wx.ScrolledWindow.__init__(self, parent, id, (0, 0), size=size, style=wx.SUNKEN_BORDER)

   
    self.parent     = parent

    self.maxWidth   = 1200

    self.maxHeight  = 800

   
    self.SetBackgroundColour("RED")

    self.SetCursor(wx.StockCursor(wx.CURSOR_PENCIL))



    self.SetVirtualSize((self.maxWidth, self.maxHeight))

    self.SetScrollRate(20,20)





    self.buffer  = wx.EmptyBitmap(self.maxWidth, self.maxHeight)

    self.buffer2 = wx.EmptyBitmap(self.maxWidth, self.maxHeight)









    self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftButtonEvent)

    self.Bind(wx.EVT_PAINT, self.OnPaint)

    self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnErase)





def OnPaint(self, event):



    dc = wx.BufferedPaintDC(self, self.buffer, wx.BUFFER_VIRTUAL_AREA)



   




def OnErase(self, event):

    pass


def OnLeftButtonEvent(self, event):

   
    dc   = wx.BufferedDC(None, self.buffer)

    gcdc = wx.GCDC(dc)

    gc   = gcdc.GetGraphicsContext()

 
    gcdc.SetBackground(wx.Brush(wx.Colour(230, 230, 230, 255)))

    gcdc.Clear()



    gc.SetBrush(wx.Brush(wx.Colour(200, 233, 240, 100)))

    gc.DrawRoundedRectangle(50, 50, 300, 300, 10)



   
    dc   = wx.BufferedDC(None, self.buffer2)

    gcdc = wx.GCDC(dc)

    gc   = gcdc.GetGraphicsContext()

 
    gcdc.SetBackground(wx.Brush(wx.Colour(0, 0, 0)))

    gcdc.Clear()



    gc.SetBrush(wx.Brush(wx.Colour(0, 255, 0, 100)))

    gc.DrawRoundedRectangle(100, 100, 300, 300, 100)



    dc   = wx.BufferedDC(None, self.buffer)

    gcdc = wx.GCDC(dc)

    gc   = gcdc.GetGraphicsContext()





    # if we put this line, we'll get rid of the black background so we
    # have shape on a transparent background, but it won't blend with it's first layer

    # because it's blended with the black background
    #



    self.buffer2.SetMaskColour((0,0,0))  



    gc.DrawBitmap(self.buffer2, 0, 0, self.maxWidth, self.maxHeight)







    self.Refresh()

if name == ‘main’:

app = wx.App(False)

frame = wx.Frame(None)

canvas = FrameCanvas(frame)

frame.Show()

app.MainLoop()

``

You received this message because you are subscribed to the Google Groups “wxPython-users” group.

To unsubscribe from this group and stop receiving emails from it, send an email to wxpython-user...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.