Home > Ramblings > Transparent static text in wxPython

Transparent static text in wxPython

March 15th, 2012

For my non-geek friends, feel free to bail now.  This is a nerd post.

I’ve been spending a lot of time lately on a project that uses wxPython for its GUI.  Yesterday, I spent about five hours trying to figure out how to have a static text widget that would have a transparent background.  My application had a gradient background, and I wanted that to show through under the text.

After a bunch of Googling, I found lots of requests for such a widget, but I didn’t find any good explanations on how to do it.  Fortunately, I did figure it out, and as is often the case, the solution was straightforward in hindsight. In the hope that I’ll save somebody a headache, here’s some code for a transparent static text widget:

"""
Static text with transparent background
"""

import wx

class TransparentText(wx.StaticText):
  def __init__(self, parent, id=wx.ID_ANY, label='', 
               pos=wx.DefaultPosition, size=wx.DefaultSize, 
               style=wx.TRANSPARENT_WINDOW, name='transparenttext'):
    wx.StaticText.__init__(self, parent, id, label, pos, size, style, name)

    self.Bind(wx.EVT_PAINT, self.on_paint)
    self.Bind(wx.EVT_ERASE_BACKGROUND, lambda event: None)
    self.Bind(wx.EVT_SIZE, self.on_size)

  def on_paint(self, event):
    bdc = wx.PaintDC(self)
    dc = wx.GCDC(bdc)

    font_face = self.GetFont()
    font_color = self.GetForegroundColour()

    dc.SetFont(font_face)
    dc.SetTextForeground(font_color)
    dc.DrawText(self.GetLabel(), 0, 0)

  def on_size(self, event):
    self.Refresh()
    event.Skip()

A couple of key things: First the style of the widget is wx.TRANSPARENT_WINDOW (all controls are windows).  Second, GCDC is used in on_paint(), because the normal DC doesn’t support transparency very well.

Unfortunately, many of the other widgets in wxPython have a similar lack of transparency support, so I ended up punting and redesigning without a gradient background. However, if I want to go back in the future and create more custom transparent widgets, this approach seems viable.

  1. Brian
    March 15th, 2012 at 14:50 | #1

    You should go to Stack Overflow and respond to questions that your solution solves.

  2. keacher
    March 16th, 2012 at 14:33 | #2

    @Brian Good idea. I haven’t been active on Stack Overflow, but this is a good opportunity to start!

  3. Eowyn
    September 20th, 2012 at 10:48 | #3

    Doesn’t work nicely with SetLabel, but great to see how this can be done!

  4. Pieter
    November 2nd, 2012 at 22:14 | #4

    I am not a nerd, but glad I did not bail out.
    Your solution is just what the doctor ordered (for me), and yes, 20/20 hindsight has a habit of beating most other visions. I was blitting to and fro, It works but is very convoluted compared with your solution.

  5. Taw
    August 28th, 2013 at 19:44 | #5

    Awesome. Very nice solution to something that I have seen posted numerous times. I was able to add your class to my code and it does exactly what I needed.
    I love it when other do my work for me!

Comments are closed.