Here is a quick hack job based on the wxPython Demo. It works on Python 3.8.10 + wxPython 4.1.1 gtk3 (phoenix) wxWidgets 3.1.5 + Linux Mint 20.2.
import wx
class TestFrame(wx.Frame):
def __init__(self, parent, text):
self.text = text
wx.Frame.__init__(self, parent, -1, "",
style=wx.FRAME_SHAPED |
wx.SIMPLE_BORDER |
wx.FRAME_NO_TASKBAR |
wx.STAY_ON_TOP)
size = (200, 32)
foreground = wx.BLUE
background = wx.YELLOW
self.hasShape = False
self.delta = (0,0)
self.Bind(wx.EVT_LEFT_UP, self.OnExit)
self.Bind(wx.EVT_PAINT, self.OnPaint)
self.bmp = self.CreateBitmap(size, text, foreground, background)
w, h = self.bmp.GetWidth(), self.bmp.GetHeight()
self.SetClientSize( (w, h) )
self.SetToolTip("Left-click to close the window")
if wx.Platform == "__WXGTK__":
# wxGTK requires that the window be created before you can
# set its shape, so delay the call to SetWindowShape until
# this event.
self.Bind(wx.EVT_WINDOW_CREATE, self.SetWindowShape)
else:
# On wxMSW and wxMac the window has already been created, so go for it.
self.SetWindowShape()
dc = wx.ClientDC(self)
dc.DrawBitmap(self.bmp, 0, 0, True)
def CreateBitmap(self, size, text, foreground, background):
width, height = size
radius = 15
bitmap = wx.Bitmap(width, height)
dc = wx.MemoryDC(bitmap)
# Make the bitmap transparent so the corners don't show
dc.SetBrush(wx.TRANSPARENT_BRUSH)
dc.Clear()
pen = wx.Pen(foreground, 1)
dc.SetPen(pen)
brush = wx.Brush(background)
dc.SetBrush(brush)
dc.DrawRoundedRectangle(0, 0, width, height, radius)
# Draw the text in the rounded rectangle
w, h = dc.GetSize()
dc.SetTextForeground(foreground)
tw, th = dc.GetTextExtent(text)
dc.DrawText(text, (w - tw) // 2, (h - th) // 2)
del dc
image = bitmap.ConvertToImage()
image.ConvertAlphaToMask()
return wx.Bitmap(image)
def SetWindowShape(self, *evt):
# Use the bitmap's mask to create a wx.Region
r = wx.Region(self.bmp)
# NOTE: Starting in 4.1 you can also get a wx.Region directly from
# a wx.Image, so you can save a step if you don't need it as a wx.Bitmap
# for anything else.
#r = self.img.ConvertToRegion()
# Use the region to set the frame's shape
self.hasShape = self.SetShape(r)
def OnPaint(self, evt):
dc = wx.PaintDC(self)
dc.DrawBitmap(self.bmp, 0,0, True)
def OnExit(self, evt):
self.Close()
if __name__ == "__main__":
app = wx.App()
frame = TestFrame(None, "This is the text")
frame.Show()
frame.Centre()
app.MainLoop()
Edit: Apologies, I’ve just noticed that it’s not actually working properly because the corners aren’t transparent…