How to Draw/create the round edge rectangular panel control

I am trying to show the status information on screen after action button fired. But, I am having issue to create the round edge rectangular panel control(attached sample image).Is there anyone to have any approach to draw/create the round edge rectangular panel control.

This is round edge rectangular panel image just i want to draw
image ![image|239x43]

Thanks
Ambesh kumar

Perhaps you could use the top level window’s SetShape() method?

See the ShapedWindow example under Miscellaneous in the wxPython Demo for ideas.

Hi RichardT,

Thank you for your suggestion.
I have tried to use setShape() for drawing the round edge rectangular Frame/Panel. but it might be something happen wrong so that i couldn’t achieve the result. i am sharing my code as below

import wx

class TestFrame(wx.Frame):
def init(self, width, height):
wx.Frame.init(self, None,
style = wx.STAY_ON_TOP |
wx.FRAME_SHAPED,
size=(width, height))
self.SetTransparent(180)
b = wx.EmptyBitmap(width-10, height-10)
dc = wx.MemoryDC()
dc.SelectObject(b)
dc.SetBackground(wx.Brush(‘black’))
dc.Clear()
dc.SetBrush(wx.TRANSPARENT_BRUSH)
dc.SetPen(wx.Pen(‘red’, 4))
dc.SelectObject(wx.NullBitmap)
b.SetMaskColour(‘black’)
self.SetShape(wx.Region(b))

    self.Bind(wx.EVT_KEY_UP, self.OnKeyDown)
    self.SetBackgroundColour('light gray')
    self.Show(True)
    self.Centre()

def OnKeyDown(self, event):
    """quit if user press Esc"""
    if event.GetKeyCode() == 27:
        self.Close(force=True)
    else:
        event.Skip()

app = wx.App()
f = TestFrame(700, 50)
app.MainLoop()

If possible please share us your suggestion. Thank you in advance

Thanks
Ambesh kumar

Hi, ambesh25

Looking at ‘demo/ShapedWindow’, I think the following code will work:

        try:
            r = b.ConvertToImage().ConvertToRegion() # wx >= 4.1
        except AttributeError:
            r = wx.Region(b)
        self.SetShape(r)

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…

I’ve just spent several hours trying to find out why my code above wasn’t working correctly. There were a couple of errors in the CreateBitmap() method which I have fixed as below:

    def CreateBitmap(self, size, text, foreground, background):
        width, height = size
        radius = 10

        bitmap = wx.Bitmap(width, height, depth=32)

        dc = wx.MemoryDC(bitmap)

        dc.SetBackground(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)

After making these changes, the program did work, but only about 1% of the time - which was very frustrating. 99% of the time the corners were not transparent.

As an act of desperation, I copied the file to my new PC and amazingly it works there 100% of the time.

The 2 PCs are running the same versions of Python and wxPython. They are both running Linux Mint 20.2. The only difference is that the old PC is using the Mate desktop environment, whereas the new one is using Cinnamon.

As an act of desperation, I copied the file to my new PC and amazingly it works there 100% of the time.

The 2 PCs are running the same versions of Python and wxPython. They are both running Linux Mint 20.2. The only difference is that the old PC is using the Mate desktop environment, whereas the new one is using Cinnamon.

In other words, it’s a matter of theme(ability).

Karsten

One of the differences between Mate and Cinnamon is the window manager. Cinnamon uses Muffin, whereas Mate has 6 options:

  • Marco
  • Marco + Compositing
  • Marco + Compton
  • Metacity
  • Metacity + Compositing
  • Metacity + Compton

The default is Marco + Compositing. However some time ago it started crashing randomly. The advice on the Linux Mint forums was to switch to Marco + Compton which is what I have been running since.

I have just tested my program with all 6 settings for window manager on the machine running Mate and it’s only the 2 settings that include Compton that cause the corners to be non-transparent.

Marco + Compton:

Marco + Compositing:

When Linux Mint 20.3 is released I think I will install Cinnamon on both machines. I just wish Cinnamon’s workspace switcher allowed you to simply drag windows between workspaces on the bottom panel instead of having to open Expo.