wxPython:在已有的wx.Panel上叠加wx.Panel的好方法

5 投票
2 回答
11274 浏览
提问于 2025-04-15 12:26

我有一个 wx.Frame,里面有一个主要的 wx.Panel,里面放了几个小部件。我想在里面放一个按钮,点击后能弹出一个“帮助面板”。这个帮助面板可能也是一个 wx.Panel,我希望它能覆盖整个主 wx.Panel(不包括 wx.Frame 的菜单栏)。帮助面板上应该有一个关闭按钮,点击后可以让它消失。

有什么好的方法可以实现这个功能吗?我查过 wx.Notebook,但没找到不显示标签页的方法。

需要注意的是,我不想每次用户关闭和打开帮助面板时都去销毁再重新创建它:我只是想让它隐藏起来。

2 个回答

2

这是针对Python 3.9.4和wxPython 4.1.1更新的代码。希望大家觉得有用。原来的帖子对我帮助很大,但作为一个新手,我花了一些力气才让它在最近发布的工具上正常运行。

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()
11

有几种方法可以实现这个功能:

a) 你可以创建一个自定义的子面板,并把它的大小和位置设置为0,0,这样它就会在所有子控件的最上面。你不需要销毁它,只需显示或隐藏它就可以了。而且这个面板会随着父窗口的大小变化而调整。

b) 你可以弹出一个 wx.PopupWindow 或者它的子类,并把它放在正确的位置,设置合适的大小。

根据a)的建议,这里有一个例子,所有的控件都放在一个面板里,使用了布局管理器(sizer)。另外创建了一个单独的帮助控件,可以通过按钮来显示或隐藏,但你也可以创建一个自定义控件,让它在点击关闭时自己隐藏。

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()

撰写回答