WxPython如何实现展开后内置滚动列表的可折叠窗格
你遇到的GTK警告并非控件不兼容导致,属于wx.CollapsiblePane的使用方法错误:
Gtk-WARNING: Attempting to add a widget with type GtkScrolledWindow to a GtkExpander, but as a GtkBin subclass a GtkExpander can only contain one widget at a time; it already contains a widget of type wxPizza
原生wx.CollapsiblePane底层基于GtkExpander实现,后者属于只能容纳1个子控件的GtkBin容器,wx.CollapsiblePane本身已经内置了一个默认容器(即警告中提到的wxPizza),直接将ScrolledWindow添加到CollapsiblePane实例上,相当于给GtkExpander重复添加子控件,因此触发警告。
完全可以实现展开后内部内容可滚动的可折叠控件,共有两种成熟实现方式:
方案1:使用原生wx.CollapsiblePane实现
操作步骤:
- 创建
wx.CollapsiblePane实例 - 调用
GetPane()方法获取其内置的容器对象,所有子控件必须添加到这个容器中,不可直接添加到CollapsiblePane实例 - 创建
wx.ScrolledWindow实例,将按钮列表等内容添加到ScrolledWindow中 - 将ScrolledWindow添加到内置容器中,配套设置对应sizer布局
- 调用ScrolledWindow的
SetScrollRate(x步长, y步长)方法激活滚动功能
参考代码片段:
import wx class ScrollableCollapsibleFrame(wx.Frame): def __init__(self): super().__init__(None, title="可折叠滚动面板", size=(300, 400)) root_panel = wx.Panel(self) root_sizer = wx.BoxSizer(wx.VERTICAL) # 初始化可折叠面板 collapse_pane = wx.CollapsiblePane(root_panel, label="展开查看按钮列表") # 获取内置容器 inner_container = collapse_pane.GetPane() inner_sizer = wx.BoxSizer(wx.VERTICAL) # 初始化滚动窗口 scrolled_win = wx.ScrolledWindow(inner_container, style=wx.VSCROLL) scrolled_win.SetScrollRate(0, 10) scroll_sizer = wx.BoxSizer(wx.VERTICAL) # 填充测试按钮,超出高度自动触发滚动 for idx in range(30): scroll_sizer.Add( wx.Button(scrolled_win, label=f"测试按钮 {idx+1}"), flag=wx.EXPAND | wx.ALL, border=2 ) scrolled_win.SetSizer(scroll_sizer) inner_sizer.Add(scrolled_win, proportion=1, flag=wx.EXPAND) inner_container.SetSizer(inner_sizer) root_sizer.Add(collapse_pane, proportion=1, flag=wx.EXPAND | wx.ALL, border=10) root_panel.SetSizer(root_sizer) self.Show() if __name__ == "__main__": app = wx.App() ScrollableCollapsibleFrame() app.MainLoop()
方案2:使用AGW库的PyCollapsiblePane实现
AGW提供的PyCollapsiblePane没有默认内置容器,可直接添加子控件,布局逻辑更简单:
- 外层创建
PyCollapsiblePane实例 - 直接将
wx.ScrolledWindow添加到PyCollapsiblePane中 - 将按钮列表等内容添加到ScrolledWindow中,配置布局和滚动参数即可
将CollapsiblePane放在ScrolledWindow内部的用法,实现的是「整个可折叠面板跟随页面滚动」的效果,和你需要的「折叠面板展开后内部内容独立滚动」的需求不符,注意区分布局层级。
Collapsible Pane内部嵌套ScrolledWindow的用法本身完全合规,不存在控件不兼容问题,只要按照规范添加子控件即可正常运行。
内容的提问来源于stack exchange,提问作者John C

