【问题标题】:wxPython: A foldable panel widgetwxPython:可折叠面板小部件
【发布时间】:2009-05-03 12:04:04
【问题描述】:

我有我的主程序窗口,我想制作一个可折叠面板。我的意思是,一个与窗口的一侧对齐的面板,带有一个折叠/展开按钮。重要的是,当面板折叠/展开时,其他小部件会相应地改变它们的大小以利用它们所拥有的空间。

我该怎么做?

【问题讨论】:

    标签: python user-interface wxpython widget


    【解决方案1】:

    这是使用 wx.SplitterWindow 的一种方法

    import wx, wx.calendar
    
    
    class FoldableWindowContainer(wx.Panel):
        def __init__(self, parent, left, right):
            wx.Panel.__init__(self, parent)
    
            sizer = wx.BoxSizer(wx.HORIZONTAL)
            self.SetSizer(sizer)
            self.splitter = wx.SplitterWindow(self, style=wx.SP_LIVE_UPDATE)
            left.Reparent(self.splitter)
            right.Reparent(self.splitter)
            self.left = left
            self.right = right
            self.splitter.SplitVertically(self.left, self.right)
            self.splitter.SetMinimumPaneSize(50)
            self.sash_pos = self.splitter.SashPosition
            sizer.Add(self.splitter, 1, wx.EXPAND)
    
            fold_button = wx.Button(self, size=(10, -1))
            fold_button.Bind(wx.EVT_BUTTON, self.On_FoldToggle)
            sizer.Add(fold_button, 0, wx.EXPAND)
    
        def On_FoldToggle(self, event):
            if self.splitter.IsSplit():
                self.sash_pos = self.splitter.SashPosition
                self.splitter.Unsplit()
            else:
                self.splitter.SplitVertically(self.left, self.right, self.sash_pos)
    
    
    class FoldTest(wx.Frame):
        def __init__(self):
            wx.Frame.__init__(self, None)
    
            left = wx.Panel(self, style=wx.BORDER_SUNKEN)
            right = wx.Panel(self, style=wx.BORDER_SUNKEN)
    
            left_sizer = wx.BoxSizer(wx.VERTICAL)
            left.SetSizer(left_sizer)
            left_sizer.Add(wx.calendar.CalendarCtrl(left), 1, wx.EXPAND | wx.ALL, 5)
            left_sizer.Add(wx.Button(left, label="Act"), 0, wx.EXPAND | wx.ALL, 5)
    
            right_sizer = wx.BoxSizer(wx.VERTICAL)
            right.SetSizer(right_sizer)
            right_sizer.Add(
                wx.StaticText(right, label="Fold panel", style=wx.BORDER_RAISED),
                1, wx.EXPAND | wx.ALL, 5
            )
    
            FoldableWindowContainer(self, left, right)
    
    
    app = wx.PySimpleApp()
    app.TopWindow = FoldTest()
    app.TopWindow.Show()
    app.MainLoop()
    

    另外,请查看 wxPython 演示中的 wx.CollapsiblePane。

    【讨论】:

    • 效果很好!现在,后续问题。我想制作一个可以自动执行此操作的小部件,因此我不必自己创建按钮和大小调整器。我该如何着手去做呢?我在过去的一个小时里一直在尝试,但遇到了一些问题:假设我将我的类称为 FoldableWindowContainer(简称 FWC)。我应该继承 SplitterWindow 吗?或者我应该继承 Window,并在其中创建一个 SplitterWindow?因为我尝试过这样做,但问题是,如何将 Windows 添加到 FWC?我的意思是,谁是他们的父母,FWC 还是里面的 SplitterWindow?请指教。
    • 您可以使用我给出的仅来自 wx.Panel 的子类而不是 wx.Frame 的示例,并将进入拆分器窗口的两个面板作为参数传递给 init (使用它,以便这些面板和您的 FWC 具有相同的父级)。另外一点,您可能会发现 wx.SplitterWindow 的 SetSashGravity 方法很有用。
    • 哦,是的,您应该在 FWC 的 init 中重新设置面板的父级。我进行了更改并更新了我的示例。
    【解决方案2】:

    如果您正确创建层次结构,wxPython(以及 Swing 和其他)的布局管理器应该能够为您执行此操作。让我们假设它绑定到右侧,因此:

    +-----------------------------+
    |+----------------+ +--------+|
    ||                | | This is||
    ||                | | your   ||
    ||   Other stuff  | | panel  ||
    ||                | +--------+|
    ||                | +--------+|
    ||                | | Another||
    ||                | | panel  ||
    |+----------------+ +--------+|
    +-----------------------------+
    

    如果您的布局正确,您将拥有一个包含两列的顶级布局,一列用于其他内容,另一列用于右侧容器。

    那个容器将有它自己的布局管理器,有两行,一用于顶部面板,一用于底部。

    这样,当您将顶部面板(您的可折叠面板)调整为更短(折叠)或更高(展开)时,布局管理器应该扩展或收缩底部面板以适应。

    显然,您可以使用更复杂的布局管理器,我选择了最简单的布局管理器来说明如何做到这一点,而不会使讨论与列/行跨度和锚点等混淆。您还可以通过反转窗口管理器(水平 垂直)来更改折叠方向。

    【讨论】:

    • 您是否建议我自己编写折叠/展开功能?我希望有一个现有的小部件。
    • 还有一件事:“容器”是指wx.Sizer吗?因为我做了一个这样的小实验:我把两个窗口放在一个sizer中,然后调整其中一个的大小。 sizer 没有适应。
    【解决方案3】:

    Toni Ruža 的原始示例,稍作修改以在 4.0/Phoenix 下工作。非常好的工作示例,谢谢 Toni!

    import wx
    import wx.adv
    
    
    class FoldableWindowContainer(wx.Panel):
        def __init__(self, parent, left, right):
            wx.Panel.__init__(self, parent)
    
            sizer = wx.BoxSizer(wx.HORIZONTAL)
            self.SetSizer(sizer)
            self.splitter = wx.SplitterWindow(self, style=wx.SP_LIVE_UPDATE)
            left.Reparent(self.splitter)
            right.Reparent(self.splitter)
            self.left = left
            self.right = right
            self.splitter.SplitVertically(self.left, self.right)
            self.splitter.SetMinimumPaneSize(50)
            self.sash_pos = self.splitter.GetSashPosition()
            sizer.Add(self.splitter, 1, wx.EXPAND)
    
            fold_button = wx.Button(self, size=(10, -1))
            fold_button.Bind(wx.EVT_BUTTON, self.On_FoldToggle)
            sizer.Add(fold_button, 0, wx.EXPAND)
    
        def On_FoldToggle(self, event):
            if self.splitter.IsSplit():
                self.sash_pos = self.splitter.GetSashPosition()
                self.splitter.Unsplit()
            else:
                self.splitter.SplitVertically(self.left, self.right, self.sash_pos)
    
    
    class FoldTest(wx.Frame):
        def __init__(self):
            wx.Frame.__init__(self, None)
    
            left = wx.Panel(self, style=wx.BORDER_SUNKEN)
            right = wx.Panel(self, style=wx.BORDER_SUNKEN)
    
            left_sizer = wx.BoxSizer(wx.VERTICAL)
            left.SetSizer(left_sizer)
            left_sizer.Add(wx.adv.CalendarCtrl(left), 1, wx.EXPAND | wx.ALL, 5)
            # left_sizer.Add(wx.Button(left, label="Act"), 0, wx.EXPAND | wx.ALL, 5)  # uncommented as unbound
    
            right_sizer = wx.BoxSizer(wx.VERTICAL)
            right.SetSizer(right_sizer)
            right_sizer.Add(wx.StaticText(right, label="Fold this panel using the thin vertical button on the right"),
                            1, wx.EXPAND | wx.ALL, 5)
    
            FoldableWindowContainer(self, left, right)
    
    
    if __name__ == '__main__':
        app = wx.App()
        ex = FoldTest()
        ex.Show()
        app.MainLoop()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-05-23
      • 1970-01-01
      • 1970-01-01
      • 2015-11-25
      • 2012-05-16
      • 2019-04-28
      • 2012-06-03
      • 1970-01-01
      相关资源
      最近更新 更多