wxPython:可折叠面板小部件
我有一个主程序窗口,我想做一个可折叠的面板。我的意思是,这个面板要靠在窗口的一侧,并且有一个可以折叠和展开的按钮。重要的是,当面板折叠或展开时,其他的控件(比如按钮、文本框等)也要相应地改变大小,以便更好地利用空间。
我该怎么做呢?
3 个回答
0
这是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()
1
wxPython(还有Swing等其他工具)的布局管理器可以帮你处理这些事情,只要你正确地建立层级结构。假设这个布局是绑定在右侧的,如下所示:
+-----------------------------+
|+----------------+ +--------+|
|| | | This is||
|| | | your ||
|| Other stuff | | panel ||
|| | +--------+|
|| | +--------+|
|| | | Another||
|| | | panel ||
|+----------------+ +--------+|
+-----------------------------+
如果你的布局设置得当,你会有一个顶层布局,分成两列,一列放其他内容,另一列放右侧的容器。
那个容器会有自己的布局管理器,分成两行,一行是上面的面板,一行是下面的面板。
这样,当你调整上面面板的大小(比如折叠成更短或展开成更高)时,布局管理器会自动调整下面面板的大小,以适应它。
当然,你可以使用更复杂的布局管理器,我这里选择了最简单的来说明如何做到这一点,而不让讨论变得复杂,比如列/行的跨越和锚点等等。你也可以通过反转窗口管理器的方向来改变折叠的方式(横向 <-> 纵向)。
5
这里有一种方法是使用 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。