[wxPython] wxBoxSizer - how to use it?

David C. Fox wrote:

Well, first, I think you want to call topsizer.Fit instead of
topsizer.SetSizeHints. Then, one way is to eliminate the
button_panel,

Thank you for your suggestion David - it works.

I've started from something similiar to your solution, but it was a
little different and wasn't work :wink: - that's why I added wxPanel.

I still like topsizer.SetSizeHints more because it doesn't allow my
dialog to be less then it's starting size. Anyway I don't like a
situation when one button come accross another - is there any other way
to forbid this?

make the buttons children of the dialog, and add the button_sizer
instead of the button_panel to the topsizer:

Your recept however don't work for wxFrame very well - if I apply it to
the wxFrame instead of wxDialog and eliminate wxPanel, I'll receive
buttons on the dark gray background instead of default light gray
background of dialogs on Windows, and this looks slovenly. Using wxPanel
again :wink: solves the problem.

Sincerely Yours,

    Victor.

Krjukov Victor wrote:

David C. Fox wrote:

Well, first, I think you want to call topsizer.Fit instead of topsizer.SetSizeHints. Then, one way is to eliminate the button_panel,

Thank you for your suggestion David - it works.

I've started from something similiar to your solution, but it was a
little different and wasn't work :wink: - that's why I added wxPanel.

I still like topsizer.SetSizeHints more because it doesn't allow my
dialog to be less then it's starting size. Anyway I don't like a
situation when one button come accross another - is there any other way
to forbid this?

You can call Fit and then SetSizeHints, but I think SetSizeHints by itself just sets the minimums to the current sizes, not to the sizes which actually fit all the controls in the dialog.

make the buttons children of the dialog, and add the button_sizer instead of the button_panel to the topsizer:

Your recept however don't work for wxFrame very well - if I apply it to
the wxFrame instead of wxDialog and eliminate wxPanel, I'll receive
buttons on the dark gray background instead of default light gray
background of dialogs on Windows, and this looks slovenly. Using wxPanel
again :wink: solves the problem.

In fact, in your original code, just adding the topsizer.Fit command before topsizer.SetSizeHints, and moving the button_sizer.Fit line after button_panel.SetSizer seemed to fix things on my system (Win98, wxPython 2.3.2, Python 1.5.2). I didn't even need the call to button_panel.Layout:

class MyDialog(wxDialog):
     def __init__(self, parent, id, title):
         wxDialog.__init__(self, parent, id, title,
                           style = wxDEFAULT_DIALOG_STYLE |
wxRESIZE_BORDER)

         topsizer = wxBoxSizer(wxVERTICAL)
         topsizer.Add(
             wxTextCtrl(self, -1, "My text.", pos = wxDefaultPosition,
                        size = wxSize(100, 60), style = wxTE_MULTILINE),
             1, wxEXPAND | wxALL, 10)

         button_panel = wxPanel(self, -1)
         button_sizer = wxBoxSizer(wxHORIZONTAL)
         button_sizer.Add(wxButton(button_panel, wxID_OK, "OK"), 0,
wxALL, 10)
         button_sizer.Add(0,0,1)
         button_sizer.Add(wxButton(button_panel, wxID_CANCEL, "Cancel"),
0, wxALL, 10)

         button_panel.SetAutoLayout(true)
         button_panel.SetSizer(button_sizer)
         button_sizer.Fit(button_panel)
# button_panel.Layout()

         topsizer.Add(button_panel, 0, wxALIGN_CENTER | wxEXPAND)

# self.Layout()
         self.SetAutoLayout(true)
         self.SetSizer(topsizer)
         topsizer.Fit(self)
         topsizer.SetSizeHints(self)

Since this solution retains the panel, it should work with a wxFrame instead of a wxDialog.

Alternatively, you could make all the controls (the text control as well as the buttons) children of a wxPanel, and make the wxPanel a child of the wxFrame. Then, you can have a topsizer for the wxPanel and a button_sizer for the button row, which you Add to the topsizer:

class MyFrame(wxFrame):
     def __init__(self, parent, id, title):
         wxFrame.__init__(self, parent, id, title)

         panel = wxPanel(self, -1)

         topsizer = wxBoxSizer(wxVERTICAL)
         topsizer.Add(
             wxTextCtrl(panel, -1, "My text.", pos = wxDefaultPosition,
                        size = wxSize(100, 60), style = wxTE_MULTILINE),
             1, wxEXPAND | wxALL, 10)

         button_sizer = wxBoxSizer(wxHORIZONTAL)
         button_sizer.Add(wxButton(panel, wxID_OK, "OK"), 0,
wxALL, 10)
         button_sizer.Add(0,0,1)
         button_sizer.Add(wxButton(panel, wxID_CANCEL, "Cancel"),
0, wxALL, 10)

         topsizer.Add(button_sizer, 0, wxALIGN_CENTER | wxEXPAND)

         panel.SetAutoLayout(true)
         panel.SetSizer(topsizer)
         topsizer.Fit(panel)
# topsizer.SetSizeHints(panel)
         fs = wxBoxSizer(wxVERTICAL)
         fs.Add(panel, 1, wxEXPAND)
         self.SetAutoLayout(true)
         self.SetSizer(fs)
         fs.Fit(self)
         fs.SetSizeHints(self)

The only downside to this is that I find I need a sizer for the frame as well (even though, with the wxPanel being the only child of the wxFrame, it is supposed to occupy the entire frame). And, in your case, you would need one anyway to call Fit and SetSizeHints on, otherwise the frame could get resized below the minimum needed to fit the controls in the panel.

David