wxPython: un widget de panneau pliable
-
03-07-2019 - |
Question
J'ai la fenêtre principale de mon programme et j'aimerais créer un panneau pliable. Ce que je veux dire, c’est un panneau qui est aligné sur l’un des côtés de la fenêtre, avec un bouton plier / déplier. Il est important que lorsque le panneau soit plié / déplié, les autres widgets changent de taille en conséquence pour tirer parti de l'espace disponible.
Comment puis-je faire cela?
La solution
Voici un moyen d'utiliser 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()
Découvrez également wx.CollapsiblePane dans les démonstrations de wxPython.
Autres conseils
Les gestionnaires de dispositions de wxPython (et de Swing et autres) devraient pouvoir le faire pour vous si vous créez correctement la hiérarchie. Supposons que cela soit lié au côté droit, ainsi:
+-----------------------------+
|+----------------+ +--------+|
|| | | This is||
|| | | your ||
|| Other stuff | | panel ||
|| | +--------+|
|| | +--------+|
|| | | Another||
|| | | panel ||
|+----------------+ +--------+|
+-----------------------------+
Si votre présentation est correctement réalisée, vous disposerez d'une disposition de niveau supérieur avec deux colonnes, une pour les autres éléments et une pour le conteneur de droite.
Ce conteneur aura son propre gestionnaire de disposition avec deux lignes, une pour le panneau supérieur et une pour le bas.
Ainsi, lorsque vous redimensionnez le panneau supérieur (votre panneau pliable) afin qu’il soit plus court (plié) ou plus grand (déplié), le gestionnaire de disposition doit développer ou réduire le panneau inférieur pour s’adapter.
Évidemment, vous pouvez utiliser des gestionnaires de disposition plus compliqués. J'ai choisi les plus simples pour illustrer comment le faire sans encombrer la discussion avec des étendues de colonnes / lignes, des ancres, etc. Vous pouvez également modifier la direction du repliement en inversant les gestionnaires de fenêtres (horizontal & Lt; - & Gt; vertical).
L'exemple original de Toni Ru & # 382; a, avec de légères modifications pour fonctionner sous 4.0 / Phoenix. Très bel exemple de travail, merci 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()