Monday, March 28, 2011

How do I layout a 3 pane window using wxPython?

I am trying to find a simple way to layout a 3 pane window using wxPython.

I want to have a tree list in the left pane, then have a right pane that is split into two - with an edit component in the top part and a grid component in the bottom part.

Something along the lines of:

--------------------------------------
|             |                      |
|             |        Edit          |
|  Tree       |        Control       |
|  Control    |                      |
|             |----------------------|
|             |                      |
|             |        Grid          |
|             |                      |
--------------------------------------

I would like the window to be re-sizable and give the user the ability to change the (relative) size of each of the components within the windows by dragging the borders.

I figure that I need some combination of sizers and/or splitter-window components but can't find a decent example of this kind of window in the documentation or on the web.

From stackoverflow
  • You should use wxSplitter, here's an example. Another one here. And another.

  • First of all download wxGlade a gui builder for wxPython (alternative XRCed, i prefere wxGlade).

    Then you have to decide if you want to use a GridSizer or a Splitter and you are done. Below you find both (between Tree and right side is a GridSizer -> resizes automatically). Between Edit and GridCtrl is a Sizer (manual Resize).

    Regards.

    one minute work without entering a single line of code:

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    # generated by wxGlade 0.6.3 on Sat Feb 07 10:02:31 2009
    
    import wx
    import wx.grid
    
    # begin wxGlade: extracode
    # end wxGlade
    
    
    
    class MyDialog(wx.Dialog):
        def __init__(self, *args, **kwds):
            # begin wxGlade: MyDialog.__init__
            kwds["style"] = wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER|wx.THICK_FRAME
            wx.Dialog.__init__(self, *args, **kwds)
            self.window_1 = wx.SplitterWindow(self, -1, style=wx.SP_3D|wx.SP_BORDER)
            self.tree_ctrl_1 = wx.TreeCtrl(self, -1, style=wx.TR_HAS_BUTTONS|wx.TR_LINES_AT_ROOT|wx.TR_DEFAULT_STYLE|wx.SUNKEN_BORDER)
            self.text_ctrl_1 = wx.TextCtrl(self.window_1, -1, "This is the Edit", style=wx.TE_MULTILINE)
            self.grid_1 = wx.grid.Grid(self.window_1, -1, size=(1, 1))
    
            self.__set_properties()
            self.__do_layout()
            # end wxGlade
    
        def __set_properties(self):
            # begin wxGlade: MyDialog.__set_properties
            self.SetTitle("dialog_1")
            self.grid_1.CreateGrid(10, 3)
            # end wxGlade
    
        def __do_layout(self):
            # begin wxGlade: MyDialog.__do_layout
            grid_sizer_1 = wx.FlexGridSizer(1, 2, 3, 3)
            grid_sizer_1.Add(self.tree_ctrl_1, 1, wx.EXPAND, 0)
            self.window_1.SplitHorizontally(self.text_ctrl_1, self.grid_1)
            grid_sizer_1.Add(self.window_1, 1, wx.EXPAND, 0)
            self.SetSizer(grid_sizer_1)
            grid_sizer_1.Fit(self)
            grid_sizer_1.AddGrowableRow(0)
            grid_sizer_1.AddGrowableCol(0)
            grid_sizer_1.AddGrowableCol(1)
            self.Layout()
            # end wxGlade
    
    # end of class MyDialog
    
    
    class MyApp(wx.App):
        def OnInit(self):
            wx.InitAllImageHandlers()
            mainDlg = MyDialog(None, -1, "")
            self.SetTopWindow(mainDlg)
            mainDlg.Show()
            return 1
    
    # end of class MyApp
    
    if __name__ == "__main__":
        app = MyApp(0)
        app.MainLoop()
    
    andy47 : Thanks, that is what I was looking for. Just to be contrary I replicated the layout (somewhat) using XRCed and am using that in my application.
  • You could consider using the wx.aui advanced user interface module, as it allows you to build UIs like this very easily. Also the user can then minimise, maximise, and drag the panes around as they see fit, or not. It's pretty flexible. I actually find it easier to lay out this sort of UI with the aui toolkit, rather than with grids and splitters. Plus all the fancy buttons make apps look cooler. :)

    There is a nice example in the official demos, called AUI_DockingWindowMgr.

  • This is a very simple layout using wx.aui and three panels. I guess you can easily adapt it to suit your needs.

    Orjanp...

    import wx
    import wx.aui
    
    class MyFrame(wx.Frame):
        def __init__(self, *args, **kwargs):
         wx.Frame.__init__(self, *args, **kwargs)
    
         self.mgr = wx.aui.AuiManager(self)
    
         leftpanel = wx.Panel(self, -1, size = (200, 150))
         rightpanel = wx.Panel(self, -1, size = (200, 150))
         bottompanel = wx.Panel(self, -1, size = (200, 150))
    
         self.mgr.AddPane(leftpanel, wx.aui.AuiPaneInfo().Bottom())
         self.mgr.AddPane(rightpanel, wx.aui.AuiPaneInfo().Left().Layer(1))
         self.mgr.AddPane(bottompanel, wx.aui.AuiPaneInfo().Center().Layer(2))
    
         self.mgr.Update()
    
    
    class MyApp(wx.App):
        def OnInit(self):
         frame = MyFrame(None, -1, '07_wxaui.py')
         frame.Show()
         self.SetTopWindow(frame)
         return 1
    
    if __name__ == "__main__":
        app = MyApp(0)
        app.MainLoop()
    

0 comments:

Post a Comment