Search code examples
pythonwxpython

Why simple wxPython application looks broken on the start?


I'm trying to create my first simple but real application based on wxPython. And I'm facing many strange things which are not discribed in the basic tutorial on the wxPython home site. Here

Here is first one. I made an layout of some control on the frame and see that right after the start of the application the layout is broken. But right after resizing the applocation's window it becomes like I designed... almost So then I used wxGlade for generating code and I got the same problem. Here is the video which can provide details of the problem I faced with http://screencast.com/t/COmqye7dlwzA

As you can see after resizing it becomes better, but still it has some weird element in the top left coner of the panel 'panel_3'

And here is the code generated by wxGlade:

#!/usr/bin/env python
# -*- coding: iso-8859-15 -*-
# generated by wxGlade 0.6.5 (standalone edition) on Wed Feb 29 14:03:09 2012

import wx

# begin wxGlade: extracode
# end wxGlade


class MyFrame(wx.Frame):
    def __init__(self, *args, **kwds):
        # begin wxGlade: MyFrame.__init__
        kwds["style"] = wx.DEFAULT_FRAME_STYLE
        wx.Frame.__init__(self, *args, **kwds)
        self.panel_2 = wx.Panel(self, -1)
        self.text_ctrl_3 = wx.TextCtrl(self.panel_2, -1, "")
        self.text_ctrl_3_copy = wx.TextCtrl(self.panel_2, -1, "")
        self.text_ctrl_3_copy_1 = wx.TextCtrl(self.panel_2, -1, "")
        self.button_2 = wx.Button(self.panel_2, -1, "button_2")
        self.panel_3 = wx.Panel(self.panel_2, -1)

        self.__set_properties()
        self.__do_layout()
        # end wxGlade

    def __set_properties(self):
        # begin wxGlade: MyFrame.__set_properties
        self.SetTitle("frame_1")
        self.SetSize((519, 333))
        self.text_ctrl_3.SetMinSize((50, -1))
        self.text_ctrl_3_copy.SetMinSize((50, -1))
        self.text_ctrl_3_copy_1.SetMinSize((50, -1))
        self.panel_3.SetBackgroundColour(wx.Colour(255, 255, 255))
        # end wxGlade

    def __do_layout(self):
        # begin wxGlade: MyFrame.__do_layout
        sizer_1 = wx.BoxSizer(wx.HORIZONTAL)
        main_sizer_0 = wx.BoxSizer(wx.HORIZONTAL)
        vsizer_left_1 = wx.BoxSizer(wx.VERTICAL)
        hsizer_params_2 = wx.BoxSizer(wx.HORIZONTAL)
        hsizer_params_2.Add(self.text_ctrl_3, 0, wx.LEFT | wx.RIGHT | wx.TOP, 5)
        hsizer_params_2.Add(self.text_ctrl_3_copy, 0, wx.LEFT | wx.RIGHT | wx.TOP, 5)
        hsizer_params_2.Add(self.text_ctrl_3_copy_1, 0, wx.LEFT | wx.RIGHT | wx.TOP, 5)
        vsizer_left_1.Add(hsizer_params_2, 0, wx.EXPAND, 0)
        vsizer_left_1.Add(self.button_2, 0, wx.ALL | wx.ALIGN_CENTER_HORIZONTAL, 5)
        main_sizer_0.Add(vsizer_left_1, 0, wx.EXPAND, 0)
        main_sizer_0.Add(self.panel_3, 1, wx.ALL | wx.EXPAND, 5)
        self.panel_2.SetSizer(main_sizer_0)
        sizer_1.Add(self.panel_2, 1, wx.EXPAND, 0)
        self.SetSizer(sizer_1)
        self.Layout()
        # end wxGlade

# end of class MyFrame
if __name__ == "__main__":
    app = wx.PySimpleApp(0)
    wx.InitAllImageHandlers()
    frame_1 = MyFrame(None, -1, "")
    app.SetTopWindow(frame_1)
    frame_1.Show()
    app.MainLoop()

================================

Update

So what I found out:

  1. Widget Inspection Tool showed that panel_3 has panel_2 as a parent. I think it's correct

  2. If I put 'sizer_1.Layout()' right before 'self.Layout()' in the __do_layout method it fix everything. And there is no weird thing in the top left coner of the panel_3. I think that was a mark remained by the first TextControl

  3. Another interesting thig is that I can remove 'self.Layout()' and the aplication still will look fine.

  4. Also I've tried put in the end of the __do_layout method 'self.panel_2.Fit()' or 'self.panel_2.Layout()'. In both cases the application was still looking good

I've read about Fit() and found out that does similar thigs as Layout(). Am I wrong ? And what is the difference between them ? And which method is better ? And why do I need to layout top element in the frame to make the application look correct and Frame.Layout() doesn't do its job ?


Solution

  • I am unable to replicate this issue on Windows 7, wxPython 2.9.3.1, Python 2.6.6. However, when you see that issue where you can resize the frame and make everything pop into place, that usually means you need to put a Layout() call somewhere. Usually, you just need to call the frame or the top sizer's Layout() command right before your show it.

    It looks like you already have that though. The weird widget in panel_3 looks like something has the wrong parent, but since I don't see that issue when I run it, I can't diagnose it. Fortunately, there's a Widget Inspection Tool that you can use to figure out layout problems and lots of other things with. Here's a link: http://wiki.wxpython.org/Widget%20Inspection%20Tool

    You should by able to use that to find out which widget that is and what its parent it too. Which will give you the information needed to fix it.

    UPDATE:

    Layout basically makes the widgets lay themselves out. It kind of forces a refresh. Fit will make them take up the smallest amount of space. I'm not sure why the frame's Layout isn't working in this case on your machine. As I mentioned, it works fine for me. Ask on the wxPython mailing list to get a full answer as that's where the wx developers are.