chow
chow

Reputation: 484

wxPython Panel is two shades of gray?

sure this is easy for you. :) But I am trying to open a "preferences" menu and have it pop up and display the applications stored preferences. My issue is now cosmetic, I have no idea what the little "tetris piece" is on the upper left corner of my app. It is the color that I want to fill the entire frame, but I can't quite figure out how to do that.

Here's an image:

enter image description here

Here's my panel code re: the sizer in use:

def __init__(self):
    """Constructor"""
    import wx.lib.inspection
    wx.lib.inspection.InspectionTool().Show()                    

    wx.Frame.__init__(self, None, title="Title Options", size=(520, 390))

    prefPanel = wx.Panel(self)
    prefPanel = self

    # SET THE SIZER OBJECT UP
    prefSizer = wx.GridBagSizer(13, 9)

    # SET BASELINE INDEX VARIABLES
    xIndex = 0
    yIndex = 0

# DEFAULT DATABSE EXTENSIONS
    self.tc_DBExt = wx.TextCtrl(prefPanel, -1, "", (0,0), (150,21))
    self.label_DBExt = wx.StaticText(prefPanel, label="Default Database Extensions:")
    help_tc_DBExt= "Enter this as: *.<extension>"
    self.tc_DBExt.SetToolTip(wx.ToolTip(help_tc_DBExt))        
    self.tc_DBExt.Value = guiFunctions.configMe("general", "database_extensions")

    prefSizer.Add(self.label_DBExt, pos=(xIndex, 0), flag=wx.LEFT|wx.ALIGN_CENTER_VERTICAL|wx.TOP, border=10)
    prefSizer.Add(self.tc_DBExt, pos=(xIndex, 1), span=(1,5), flag=wx.EXPAND|wx.LEFT|wx.ALIGN_CENTER_VERTICAL|wx.TOP, border=10).SetMinSize((200,22))


    panel.SetSizer(sizer2)
    sizer2.Fit(panel)

    panel.Refresh()
    panel.Update()
    panel.Layout()

How do I get the little guy up in that lefthand corner to fill the entire panel?

UPDATE: Added widget info in case I am applying things in the wrong order...

Upvotes: 0

Views: 656

Answers (4)

Mike Driscoll
Mike Driscoll

Reputation: 33071

This is a parenting issue:

prefPanel = wx.Panel(self)
prefPanel = self

First you set the prefPanel object to be a wx.Panel, then you override it and set it back to the frame (i.e. self). Remove the second line and the code should work correctly.

You almost always want to have a panel as the ONLY child of a frame. Everything else should be a child of the panel. This gives the right coloring. It also enables the ability to tab between widgets.

Upvotes: 0

nepix32
nepix32

Reputation: 3177

Short answer: You may or may not have a parent panel, but you did not make it sizing properly. Because wx.Frame on Windows has a dark gray background, it will shine through if you do not use a wx.Panel instead (and make it size properly).

Long answer: Tried to include a minimum running example from your code. It looks ugly (TextCtrl and Button), because the definition panel comes from outside and it is very difficult to synchronize their sizers. It would be much better to do all element creation/sizing in one wx.Panel/wx.Frame. All my comments to your code are include in triple quotes and should give you an idea why that what you are trying to do is complicated/bad/simple not working.

import wx

class panel_class(wx.Panel):
    def __init__(self, *args, **kwds):
        """Trying to implement your magic ``panel```"""
        wx.Panel.__init__(self, *args, **kwds)
        pnl = self
        szmain = wx.BoxSizer(wx.HORIZONTAL)
        szmain.Add(wx.TextCtrl(pnl, -1, 'Database path'), 1, wx.EXPAND)
        szmain.Add(wx.Button(pnl, -1, 'Database path'), 0, wx.EXPAND)
        pnl.SetSizer(szmain)


class myframe(wx.Frame):
    def __init__(self, *args, **kwds):
        """Constructor"""

        wx.Frame.__init__(self, *args, **kwds)#None, title="Title Options", size=(520, 390))

        prefPanel = wx.Panel(self)

        """This makes no sense: according to the wx.Frame.__init__ above self is a wx.Frame."""
#         prefPanel = self

        # SET THE SIZER OBJECT UP
        prefSizer = wx.GridBagSizer(13, 9)

        # SET BASELINE INDEX VARIABLES
        xIndex = 0
        yIndex = 0

        # DEFAULT DATABSE EXTENSIONS
        self.tc_DBExt = wx.TextCtrl(prefPanel, -1, "", (0,0), (150,21))
        self.label_DBExt = wx.StaticText(prefPanel, label="Default Database Extensions:")
        help_tc_DBExt= "Enter this as: *.<extension>"
        self.tc_DBExt.SetToolTip(wx.ToolTip(help_tc_DBExt))
        """Replaced with something static."""
        self.tc_DBExt.Value = 'conftxt'#guiFunctions.configMe("general", "database_extensions")

        prefSizer.Add(self.label_DBExt, pos=(xIndex, 0), flag=wx.LEFT|wx.ALIGN_CENTER_VERTICAL|wx.TOP, border=10)
        prefSizer.Add(self.tc_DBExt, pos=(xIndex, 1), span=(1,5), flag=wx.EXPAND|wx.LEFT|wx.ALIGN_CENTER_VERTICAL|wx.TOP, border=10).SetMinSize((200,22))

        """Assuming panel definition from outside.

        It has to be created here. If it is to be created **before**
        the parent is created, it is very complicated to create it with a
        dummy parent and ``Reparent`` it to this Frame/Panel. Don't do that."""

        panel = panel_class(prefPanel, -1)

        """Attach ``panel`` to a sizer in **this** hierarchy
        It looks disconnected, because it has brought already it's own
        sizer, which is child to the GridBagSizer.""" 
        xindex = 1
        prefSizer.Add(panel, pos=(xindex, 0), span=(1,5), flag=wx.EXPAND|wx.LEFT|wx.ALIGN_CENTER_VERTICAL|wx.TOP, border=10).SetMinSize((200,22))

        """You have to tell wxPython somehow to what element the sizer is coupled (in this case to the main pane)l"""
        prefPanel.SetSizer(prefSizer)

        """I have no idea """
        #panel.SetSizer(sizer2)
        #sizer2.Fit(panel)

        """Normally not needed/happening automagically on standard controls"""    
        #panel.Refresh()
        #panel.Update()
        #panel.Layout()

    def add_panel_to_layout(self):
        pass

if __name__ == '__main__':
    app = wx.App(0)

    frm = myframe(None, -1,  title="Title Options", size=(520, 390))

    frm.Show()

    """Call it here **after** all elements have been created"""
    import wx.lib.inspection
    wx.lib.inspection.InspectionTool().Show()
    app.MainLoop()

Rules for working with Sizers in wxPython:

  • Always use a wx.Panel as parent for your controls. It does not matter if your controls are themselves parented on panels, you can stack them atop as many layers as you want. If you parent direct to a wx.Frame, you will get the ugly grey background on Windows.
  • Define your control objects (can again be a panel)
  • Select an appropriate sizer
  • Layout all your elements in the sizer
  • IMPORTANT: tell your main sizer to which parent element to orient itself (main_panel.SetSizer(mymainsizer))
  • Tell the sizer of the main panel which size of the panel parent to adapt to (mymainsizer.Fit(self), assuming self is the parent of main_panel. Use self.SetSize((<w>, <h>)) if Fit goes wrong.

Example sizer for this question

Upvotes: 2

Steve Barnes
Steve Barnes

Reputation: 28370

You also need to set the panel as the parent of the other controls not the frame.

Your updated code shows another problem:

 prefPanel = wx.Panel(self)
 prefPanel = self

This is just plain wrong.

Tip: To diagnose this sort of problem you can run the Widget Inspection Control.

Upvotes: 1

g.d.d.c
g.d.d.c

Reputation: 47988

You have something parented incorrectly, likely as a result of your call to panel = self. When you do that, you're telling the interpreter to use your Frame instead of your Panel as the parent for anything that you later attempt to create via something like wx.StaticText(panel). Also dubious is the need for a call to global sizer2. How / why are you declaring sizers so far ahead of use that they need the global keyword?

Upvotes: 1

Related Questions