Django
Django

Reputation: 415

How to make nested Panel and Sizer work in wxpython

I am learning wxpython and trying to get a nested panel to work. This is an exercise to prepare for a more complex screen, hence it may look a bit complicated, but that is with a purpose ;). What I want to do is the following: Create a top frame Add a panel to it add some text and an input field to it Use a vertical boxsizer to do the panel lay out Here is how I implemented it:

import wx
class MainWindow(wx.Frame):
    def __init__(self, parent, title):
        wx.Frame.__init__(self, parent)

        #add position panel
        posPnl = wx.Panel(self)
        lbl1 = wx.StaticText(posPnl, label="Position")
        lbl2 = wx.StaticText(posPnl, label="Size")
        sizeCtrl = wx.TextCtrl(posPnl)

        posPnlSzr = wx.BoxSizer(wx.HORIZONTAL)
        posPnlSzr.Add(lbl1, 1, wx.GROW)
        posPnlSzr.Add(sizeCtrl, 1, wx.GROW)
        posPnlSzr.Add(lbl2, 1, wx.GROW)   

        #create a top leverl sizer to add to the frame itself
        mainSzr = wx.BoxSizer(wx.VERTICAL)
        mainSzr.Add(posPnlSzr)

        self.SetSizerAndFit(mainSzr)
        self.Show()


app = wx.App(False)
frame = MainWindow(None, "Trading Client")
app.MainLoop()

All i get is a small blank screen with the word 'Pos' on it. What am I doing wrong here?

Upvotes: 3

Views: 6114

Answers (2)

Mike Driscoll
Mike Driscoll

Reputation: 33071

The basic form of my applications goes something like this (parent --> child):

frame --> panel --> sizer --> widgets/sizers

For certain things, I do this:

frame --> sizer --> panel --> sizer --> widgets/sizers

I nest sizers are the time. You usually want to sketch out your GUI on paper when you're a new programmer and then draw boxes around them to try to figure out which sizers work, where you'll want to nest them, etc.

You could fix this problem just by changing self.SetSizerAndFit(mainSzr) to posPnl.SetSizerAndFit(mainSzr)

Upvotes: 0

Zeugma
Zeugma

Reputation: 32095

The logic here is to create a Panel to add controls inside, then a BoxSizer where you declare how each control you add in the Panel behaves with resizing, and eventually to set on the Panel what is the BoxSizer applied on it.

You have 2 issues.

  • First you are missing the last part of the above statement for the posPnlobject. Add this:

    posPnl.SetSizer(posPnlSzr)
    

    once you have added the controls to posPnlSzr

  • The second issue is that you are adding posSnlSzr in your mainSzr. It is wrong to do so. Again the logic is to add controls to a sizer, and you can view a Panel as a compounded control. Thus the correct code is to add posPnl into the mainSzr:

    mainSzr.Add(posPnl)
    

    As far I as read, you are trying to get posPnl automatically resized with the main window. If to add the panel so that mainSzr will actually resize it:

    mainSzr.Add(posPnl, 1, wx.GROW)
    

This gives the final source code:

#!/usr/bin/env python

import wx
class MainWindow(wx.Frame):
    def __init__(self, parent, title):
        wx.Frame.__init__(self, parent)

        #add position panel
        posPnl = wx.Panel(self)
        lbl1 = wx.StaticText(posPnl, label="Position")
        lbl2 = wx.StaticText(posPnl, label="Size")
        sizeCtrl = wx.TextCtrl(posPnl)

        posPnlSzr = wx.BoxSizer(wx.HORIZONTAL)
        posPnlSzr.Add(lbl1, 1, wx.GROW)
        posPnlSzr.Add(sizeCtrl, 1, wx.GROW)
        posPnlSzr.Add(lbl2, 1, wx.GROW)

        posPnl.SetSizer(posPnlSzr)

        #create a top leverl sizer to add to the frame itself
        mainSzr = wx.BoxSizer(wx.VERTICAL)
        mainSzr.Add(posPnl, 1, wx.GROW)

        self.SetSizerAndFit(mainSzr)
        self.Show()


app = wx.App(False)
frame = MainWindow(None, "Trading Client")
app.MainLoop()

Upvotes: 4

Related Questions