Pergunta

Eu tenho minha janela principal do programa, e eu gostaria de fazer um painel dobrável. O que é significativo, de um painel que está alinhada com um dos lados da janela, com um botão de dobrar / desdobrar. É importante que quando o painel fica dobrado / desdobrado, os outros widgets mudar seu tamanho de acordo para aproveitar o espaço que eles têm.

Como posso fazer isso?

Foi útil?

Solução

Aqui está uma maneira usando 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()

Além disso, confira wx.CollapsiblePane nos demos wxPython.

Outras dicas

Os gerenciadores de layout para wxPython (e Swing e outros) deve ser capaz de fazer isso para você se você criar a hierarquia corretamente. Vamos supor que ele é obrigado a do lado direito, assim:

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

Se o seu layout é bem feito, você terá um layout de nível superior com duas colunas, uma para as outras coisas e um para o recipiente do lado direito.

que recipiente terá seu gerente próprio layout com duas linhas, uma para o painel de topo, uma para o fundo.

Dessa forma, quando você redimensionar o painel de topo (seu um dobrável) para ser mais curto (dobrar) ou mais alto (desdobrar), o gerente de layout deve expandir ou contrair o painel inferior para o ajuste.

Obviamente, você pode usar gerenciadores de layout mais complicado, eu escolhi as mais simples para ilustrar como fazê-lo sem congestionar a discussão com vãos de coluna / linha e âncoras e assim por diante. Você também pode mudar a direção de dobrar, invertendo os gerenciadores de janelas (horizontal <-> vertical).

O exemplo original de Toni Ruža, com ligeiras modificações para trabalhar sob 4.0 / Phoenix. Exemplo muito bom de trabalho, graças 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()
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top