wxPython: un widget de panel plegable
-
03-07-2019 - |
Pregunta
Tengo mi ventana principal del programa y me gustaría hacer un panel plegable. Lo que quiero decir es, un panel que está alineado a uno de los lados de la ventana, con un botón de plegar / desplegar. Es importante que cuando el panel se pliegue / despliegue, los otros widgets cambien su tamaño en consecuencia para aprovechar el espacio que tienen.
¿Cómo hago esto?
Solución
Aquí hay una forma de usar 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()
Además, consulte wx.CollapsiblePane en las demostraciones de wxPython.
Otros consejos
Los administradores de diseño para wxPython (y Swing y otros) deberían poder hacerlo por usted si crea la jerarquía correctamente. Supongamos que está unido al lado derecho, por lo tanto:
+-----------------------------+
|+----------------+ +--------+|
|| | | This is||
|| | | your ||
|| Other stuff | | panel ||
|| | +--------+|
|| | +--------+|
|| | | Another||
|| | | panel ||
|+----------------+ +--------+|
+-----------------------------+
Si su diseño se realiza correctamente, tendrá un diseño de nivel superior con dos columnas, una para el otro material y otra para el contenedor del lado derecho.
Ese contenedor tendrá su propio administrador de diseño con dos filas, una para el panel superior y otra para la parte inferior.
De esa forma, cuando cambie el tamaño del panel superior (el plegable) para que sea más corto (plegado) o más alto (desplegado), el administrador de diseño debe expandir o contraer el panel inferior para que encaje.
Obviamente, puede usar administradores de diseño más complicados, he elegido los más simples para ilustrar cómo hacerlo sin saturar la discusión con espacios de columna / fila y anclas, etc. También puede cambiar la dirección de plegado invirtiendo los gestores de ventanas (horizontal & Lt; - & Gt; vertical).
El ejemplo original de Toni Ru & # 382; a, con ligeras modificaciones para trabajar bajo 4.0 / Phoenix. Muy buen ejemplo de trabajo, ¡gracias 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()