Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

wxPython: Good way to overlay a wx.Panel on an existing wx.Panel

I have a wx.Frame, in which there is a main wx.Panel with several widgets inside of it. I want one button in there to cause a "help panel" to come up. This help panel would probably be a wx.Panel, and I want it to overlay the entire main wx.Panel (not including the menu bar of the wx.Frame). There should be some sort of close button on the help button that will make it disappear again.

What is a good way to achieve this? I've looked into wx.Notebook but haven't found a way to make it not show the tabs.

Note that I don't want to destroy and recreate the help panel every time the user closes and opens it: I just want it to be hidden.

like image 784
Ram Rachum Avatar asked Jun 23 '09 12:06

Ram Rachum


2 Answers

There are several ways

a) you can create a custom child panel, and make it same size and position at 0,0 among top of all child widgets. no need of destroying it just Show/Hide it this also resizes with parent frame

b) popup a wx.PopupWindow or derived class and place and size it at correct location

so as suggest in a) here is an example, where all controls are put in panel using sizer, as separate help cntrl is created which can be shown/hidden from button, but you can create a custom cntrl which hides itself on clicking close

import wx

class MyFrame(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None)

        self.panel = wx.Panel(self)

        # create controls
        self.cntrlPanel = wx.Panel(self.panel)
        stc1 = wx.StaticText(self.cntrlPanel, label="wow it works")
        stc2 = wx.StaticText(self.cntrlPanel, label="yes it works")
        btn = wx.Button(self.cntrlPanel, label="help?")
        btn.Bind(wx.EVT_BUTTON, self._onShowHelp)

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(stc1)
        sizer.Add(stc2)
        sizer.Add(btn)
        self.cntrlPanel.SetSizer(sizer)


        # create help panel
        self.helpPanel = wx.Panel(self.panel)
        self.stcHelp = wx.StaticText(self.helpPanel, label="help help help\n"*8)
        btn = wx.Button(self.helpPanel, label="close[x]")
        btn.Bind(wx.EVT_BUTTON, self._onShowCntrls)
        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.stcHelp)
        sizer.Add(btn)
        self.helpPanel.SetSizer(sizer)
        self.helpPanel.Hide()
        self.helpPanel.Raise()
        self.helpPanel.SetBackgroundColour((240,250,240))
        self.Bind(wx.EVT_SIZE, self._onSize)

        self._onShowCntrls(None)

    def _onShowHelp(self, event):
        self.helpPanel.SetPosition((0,0))
        self.helpPanel.Show()
        self.cntrlPanel.Hide()

    def _onShowCntrls(self, event):
        self.cntrlPanel.SetPosition((0,0))
        self.helpPanel.Hide()
        self.cntrlPanel.Show()

    def _onSize(self, event):
        event.Skip()
        self.helpPanel.SetSize(self.GetClientSizeTuple())
        self.cntrlPanel.SetSize(self.GetClientSizeTuple())

app = wx.PySimpleApp()
frame = MyFrame()
frame.Show()
app.SetTopWindow(frame)
app.MainLoop()
like image 51
Anurag Uniyal Avatar answered Oct 30 '22 17:10

Anurag Uniyal


Updated code for Python 3.9.4 and wxPython 4.1.1. Hope people find it useful. The original post was useful to me, but as a neophyte, it took me some effort to have it run properly with recently released tools.

import wx

class MyFrame(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None)

        self.panel = wx.Panel(self)

        # create controls
        self.cntrlPanel = wx.Panel(self.panel)
        stc1 = wx.StaticText(self.cntrlPanel, label="wow it works")
        stc2 = wx.StaticText(self.cntrlPanel, label="yes it works")
        btn = wx.Button(self.cntrlPanel, label="help?")
        btn.Bind(wx.EVT_BUTTON, self._onShowHelp)

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(stc1)
        sizer.Add(stc2)
        sizer.Add(btn)
        self.cntrlPanel.SetSizer(sizer)

        # create help panel
        self.helpPanel = wx.Panel(self.panel)
        self.stcHelp = wx.StaticText(self.helpPanel, label="help help help\n"*8)
        btn = wx.Button(self.helpPanel, label="close[x]")
        btn.Bind(wx.EVT_BUTTON, self._onShowCntrls)

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.stcHelp)
        sizer.Add(btn)
        self.helpPanel.SetSizer(sizer)

        self.helpPanel.Hide()
        self.helpPanel.Raise()
        self.helpPanel.SetBackgroundColour((240,250,240))

        self.Bind(wx.EVT_SIZE, self._onSize)

        self._onShowCntrls(None)

    def _onShowHelp(self, event):
        self.helpPanel.SetPosition((0,0))
        self.helpPanel.Show()
        self.cntrlPanel.Hide()

    def _onShowCntrls(self, event):
        self.cntrlPanel.SetPosition((0,0))
        self.helpPanel.Hide()
        self.cntrlPanel.Show()

    def _onSize(self, event):
        event.Skip()
        self.helpPanel.SetSize(self.GetClientSize())
        self.cntrlPanel.SetSize(self.GetClientSize())

app = wx.App(False)
frame = MyFrame()
frame.Show()
app.SetTopWindow(frame)
app.MainLoop()
like image 1
Jonathan Marks Avatar answered Oct 30 '22 18:10

Jonathan Marks