wxPython transparency behavior MacOS vs Windows

I am drawing a bitmap with a transparency with DC on a transparent panel in
OnPaint. The code below works great on MacOS (meaning that I am able to
update the transparent panel on top and the underlying frame content shows
through).

MacOS:

<http://wxpython-users.1045709.n5.nabble.com/file/n5724803/macos.jpg>

On Windows, however, my bitmap does not draw and I lose the frame content
underneath (blank white frame), though the rectangle and text draw in the
OnPaint does work.

Windows:

<http://wxpython-users.1045709.n5.nabble.com/file/n5724803/windows.jpg>

I have tried wrapping my DC with GCDC as per [here][3]:

    pdc = wx.PaintDC(self.panel)
    dc = wx.GCDC(pdc)

but the result is the same.

Code:

  class MyBrowser(wx.Frame):

    def __init__(self, *args, **kwds):
      wx.Frame.__init__(self, *args, **kwds)
      sizer = wx.BoxSizer(wx.VERTICAL)
      self.browser = wx.html2.WebView.New(self)
      sizer.Add(self.browser, 1, wx.EXPAND, 10)
      self.SetSizer(sizer)
      
      self.winsize = 800
      self.zoom = 1
     
      self.SetSize((self.winsize, self.winsize))
      self.SetMaxSize((self.winsize, self.winsize))
      self.SetMinSize((self.winsize, self.winsize))

      self.panel=wx.Panel(self, -1, style=wx.TRANSPARENT_WINDOW,
size=(self.winsize, self.winsize))

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

    def OnPaint(self, evt):
      #dc = wx.PaintDC(self.panel)
      pdc = wx.PaintDC(self.panel)
      dc = wx.GCDC(pdc)
      dc.SetBrush(wx.Brush('#B1AFA3'))
      dc.SetPen(wx.TRANSPARENT_PEN)
      dc.DrawRectangle(0, 0, 145, 90)
      dc.DrawText('Wind speed: ' + '{:.2f}'.format(windspd), 14, 8)

      angle = (360.0 - winddir) + 90.0
      if angle >= 360.0:
        angle = 0.0

      if 0.0 < angle < 180.0:
        dc.DrawRotatedText('<---', 80, 72, angle)
      else:
        dc.DrawRotatedText('<---', 80, 42, angle)

      lonperpix = self.lonperpix[0]
      latperpix = self.latperpix[0]
    
      self.pixx = (self.winsize/2) + ((lon-self.lon1[0])/lonperpix)
      self.pixy = (self.winsize/2) - ((lat-self.lat1[0])/latperpix)
    
      airplane1 = wx.Image('/Users/Downloads/x_Fighter.png')
      airplane2 = airplane1.Rotate(-(math.radians(heading)), (16, 16))
      dc.DrawBitmap(wx.BitmapFromImage(airplane2), self.pixx-16, self.pixy-16)
      self.panel.Refresh()

Thanks in advance for any possible multi-platform strategies.

···

--
View this message in context: http://wxpython-users.1045709.n5.nabble.com/wxPython-transparency-behavior-MacOS-vs-Windows-tp5724803.html
Sent from the wxPython-users mailing list archive at Nabble.com.

justinh wrote:

On Windows, however, my bitmap does not draw and I lose the frame content
underneath (blank white frame), though the rectangle and text draw in the
OnPaint does work.

wx.BitmapFromImage is going to strip out the alpha. You should probably
use wxGraphicsContext.CreateBitmapFromImage to convert to a
wx.GraphicsBitmap instead of a plain wx.Bitmap.

···

--
Tim Roberts, timr@probo.com
Providenza & Boekelheide, Inc.

Thanks Tim - I'll test this out.

···

On 9/21/15, 10:02 PM, Tim Roberts wrote:

justinh wrote:

On Windows, however, my bitmap does not draw and I lose the frame content
underneath (blank white frame), though the rectangle and text draw in the
OnPaint does work.

wx.BitmapFromImage is going to strip out the alpha. You should probably
use wxGraphicsContext.CreateBitmapFromImage to convert to a
wx.GraphicsBitmap instead of a plain wx.Bitmap.

--

*Justin Hyland, PhD* | Founder, Research & Development | jhyland@computamaps.com <mailto:jhyland@computamaps.com>
Tel: +27.21.713 8630 | Mobile: +27.83.556 3464 | Fax: +27.21.713 0211
Address: Manor house, Dreyersdal Farm Rd, Bergvliet 7945, Cape Town, South Africa

Mapping your World in 3D <http://www.computamaps.com/&gt;

Tim Roberts wrote:

wx.BitmapFromImage is going to strip out the alpha. You should probably

use wxGraphicsContext.CreateBitmapFromImage to convert to a

wx.GraphicsBitmap instead of a plain wx.Bitmap.

This fixed the png import - thanks.

My problem now is getting my OnPaint event to draw text and graphics in a transparent panel ON TOP of a wx.html2.WebView browser placed within the application frame. If I comment out the browser (or not load a url) the panel graphics and text draw and update correctly. If, however, I enable the browser and load a url, the browser draw seems to take precedence over the top panel draw. I can see an edge of my panel graphics under the browser and I have output the dc to a file so I know it is being drawn.

Regarding flicker, I can suppress with ‘self.SetDoubleBuffered(True)’ calls but only for the frame or for the panel not both. I have also tried the usual EVT_ERASE_BACKGROUND and BufferedPaintDC but these didn’t have any impact.

Again, all of this is only for Windows implementation. My original code works fine on MacOS.

My current Windows strategy (this will draw the panel; uncomment the browser lines and the browser draws over the panel):

class MyBrowser(wx.Frame):

def __init__(self, *args, **kwds):
    wx.Frame.__init__(self, *args, **kwds)     
    sizer = wx.BoxSizer(wx.VERTICAL)
    #self.browser = wx.html2.WebView.New(self)
    #sizer.Add(self.browser, 1, wx.EXPAND, 10)
    self.SetSizer(sizer)
   
    #self.SetDoubleBuffered(True)
   
    self.SetSize((self.winsize, self.winsize))
    self.SetMaxSize((self.winsize, self.winsize))
    self.SetMinSize((self.winsize, self.winsize))

    self.panel=wx.Panel(self, -1, style=wx.TRANSPARENT_WINDOW, size=(self.winsize, self.winsize))

    urlstr = 'https://maps.googleapis.com/maps/api/staticmap?center=40.714728,-73.998672&zoom=11&size=600x600&maptype=terrain'
    #self.browser.LoadURL(urlstr)
                                           
    self.Bind(wx.EVT_CLOSE, self.OnClose)
    self.panel.Bind(wx.EVT_PAINT, self.OnPaint)

def OnPaint(self, evt):

    self.panel.SetDoubleBuffered(True)
   
    dc = wx.PaintDC(self.panel)
    gc = wx.GraphicsContext.Create(dc)
    gc.SetBrush(wx.Brush('#B1AFA3'))
    gc.SetPen(wx.TRANSPARENT_PEN)
    gc.DrawRectangle(0, 0, 145, 90)
    gc.DrawText('Wind speed: ' + '{:.2f}'.format(windspd), 14, 8)
   
    airplane1 = wx.Image('U:/x_Fighter.png')
    airplane2 = airplane1.Rotate(-(math.radians(heading)), (16, 16))
    airplane3 = gc.CreateBitmapFromImage(airplane2)
    gc.DrawBitmap(airplane3, self.pixx-16, self.pixy-16, 32, 32)
    self.panel.Refresh()

justinhyland6434@gmail.com wrote:

My problem now is getting my OnPaint event to draw text and graphics
in a transparent panel ON TOP of a wx.html2.WebView browser placed
within the application frame. If I comment out the browser (or not
load a url) the panel graphics and text draw and update correctly. If,
however, I enable the browser and load a url, the browser draw seems
to take precedence over the top panel draw. I can see an edge of my
panel graphics under the browser and I have output the dc to a file so
I know it is being drawn.

This is kind of an awkward design. You have two windows that you want
to be stacked on top of one another. Your short-term problem is that
you need to specify the Z-order, so you can specify which window is on
"top". In general, wx was not design to handle overlapping windows.
You should, however, be able to call self.panel.Raise() to force it to
bubble up.

But even after that, consider what you've done. You have a browser
window that is part of a sizer, controlled by that sizer, which is
attached to the frame. Then, you have your panel, which is NOT part of
a sizer, and thus will not be automatically size-adjusted. It's going
to be tricky.

···

--
Tim Roberts, timr@probo.com
Providenza & Boekelheide, Inc.

Then, you have your panel, which is NOT part of

a sizer, and thus will not be automatically size-adjusted.

Now added panel to sizer as well. Thanks - much better now.

You should, however, be able to call self.panel.Raise() to force it to

bubble up.

Calling self.panel.Raise() also didn’t get the panel to draw on top of browser.
This forced a complete rethink in strategy.

What I ended up doing was hiding the top text and graphics panel, blitting the
browser dc to a bitmap, showing the panel again and then drawing the browser
bitmap and overlapping text and graphics in my OnPaint for the panel.

A bit convoluted (especially compared to what I have implemented for Mac)
but it works.

In general, wx was not design to handle overlapping windows.

I certainly see that now for Windows.

···

On Monday, October 12, 2015 at 9:20:12 PM UTC+2, Tim Roberts wrote: