Question

I reproduced the error here;

import wx
import debug

class MyFrame(wx.Frame):


    def __init__(self, parent):

        wx.Frame.__init__(self, parent, -1, "Test")
        self.SetSize((600,500))

        vbox = wx.BoxSizer(wx.VERTICAL)
        toolbar = wx.ToolBar(self, -1, style=wx.TB_HORIZONTAL | wx.NO_BORDER)
        toolbar.Realize()
        vbox.Add(toolbar, 0, border=5)

app = wx.App(0)

frame = MyFrame(None)
app.SetTopWindow(frame)
frame.Show()

app.MainLoop()

Now wherever i add this line to add a text control;

self.control = wx.TextCtrl(self, style=wx.TE_MULTILINE)

it appears over the toolbar. I read the documentation and followed some tutorials but still i cant fully grasp the concept. How can i achieve what i want? I want the text control to appear below the toolbar and fit the remaining space.

Was it helpful?

Solution

Well, there are a couple of issues

  1. you haven't added the TextCtrl to the BoxSizer, so it won't get laid out
  2. you haven't set the sizer for the Frame

You can do something like this...

def __init__(self, parent):

    wx.Frame.__init__(self, parent, -1, "Test")
    self.SetSize((600,500))

    toolbar = wx.ToolBar(self, -1, style=wx.TB_HORIZONTAL | wx.NO_BORDER)
    toolbar.Realize()

    self.control = wx.TextCtrl(self, style=wx.TE_MULTILINE)

    vbox = wx.BoxSizer(wx.VERTICAL)
    vbox.Add(toolbar, 0, border=5)
    vbox.Add(self.control, 1, border=5)

    self.SetSizer(vbox)

...but it's probably better to use the Frame's CreateToolBar() method, then you don't have to worry about its layout...

def __init__(self, parent):

    wx.Frame.__init__(self, parent, -1, "Test")
    self.SetSize((600,500))

    toolbar = self.CreateToolBar(style=wx.TB_HORIZONTAL | wx.NO_BORDER)
    toolbar.Realize()

    self.control = wx.TextCtrl(self, style=wx.TE_MULTILINE)

    vbox = wx.BoxSizer(wx.VERTICAL)
    vbox.Add(self.control, 1, border=5)

    self.SetSizer(vbox)

...indeed, if the TextCtrl is the only other thing in the frame, you don't even need the sizer...

def __init__(self, parent):

    wx.Frame.__init__(self, parent, -1, "Test")
    self.SetSize((600,500))

    toolbar = self.CreateToolBar(style=wx.TB_HORIZONTAL | wx.NO_BORDER)
    toolbar.Realize()

    self.control = wx.TextCtrl(self, style=wx.TE_MULTILINE)

OTHER TIPS

Without seeing the actual problem code, it's hard to be sure, but I'm betting that you want this:

vbox.Add(self.control)

Or, if the TextCtrl isn't being built inside __init__, make that self.vbox.Add, and of course change the vbox references in __init__ to self.vbox.

Quoting from the docs:

The basic idea behind a box sizer is that windows will most often be laid out in rather simple basic geometry, typically in a row or a column or nested hierarchies of either. A wx.BoxSizer will lay out its items in a simple row or column, depending on the orientation parameter passed to the constructor.

This is exactly you want—you want to put a TextCtrl to get laid out vertically beneath a Toolbar. If you put them both into the same BoxSizer, this will happen automatically.

But if you put the TextCtrl directly into a Frame, and also put the BoxSizer with the Toolbar inside it into the same Frame, you haven't told wx how to lay out the controls within the Frame.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top