Window Size?

I've created a splitterwindow, with a treectrl panel in the first window. The panel doesn't fill up the entire window using wx.DefaultSize, and refuses to do otherwise. I tried simply setting it to the size of the parent, but GetSize() returns zero! Is that a bug? How can there be a visible window with zero size?

How can you make a panel fill up a window?

I'd appreciate any help. Below is my code.

import os, sys, types
import wx

from stash import stash

···

#---------------------------------------------------------------------------

class MyTreeCtrl(wx.TreeCtrl):
     def __init__(self, parent, id, pos, size, style):
         wx.TreeCtrl.__init__(self, parent, id, pos, size, style)

     def OnCompareItems(self, item1, item2):
         t1 = self.GetItemText(item1)
         t2 = self.GetItemText(item2)
         if t1 < t2: return -1
         if t1 == t2: return 0
         return 1

#---------------------------------------------------------------------------

class TestTreeCtrlPanel(wx.Panel):
     def __init__(self, parent):
         # Use the WANTS_CHARS style so the panel doesn't eat the Return key.
         wx.Panel.__init__(self, parent, -1, style=wx.WANTS_CHARS,
                           size=parent.GetSize()
                           )
         #wx.EVT_SIZE(self, self.OnSize)

         #self.log = log
         tID = wx.NewId()

         #print self.GetSize()
         self.tree = MyTreeCtrl(self, tID, wx.DefaultPosition, wx.DefaultSize,#(500,500),#
                                style = wx.TR_NO_LINES
                                    > wx.TR_TWIST_BUTTONS
                                    #| wx.TR_HAS_BUTTONS
                                    > wx.TR_EDIT_LABELS
                                     #| wx.TR_ROW_LINES
                                    #| wx.TR_HIDE_ROOT
                                    #| wx.TR_DEFAULT_STYLE
                                    )

         isz = (16,16)
         il = wx.ImageList(isz[0], isz[1])
         fldridx = il.Add(wx.ArtProvider_GetBitmap(wx.ART_FOLDER, wx.ART_OTHER, isz))
         fldropenidx = il.Add(wx.ArtProvider_GetBitmap(wx.ART_FILE_OPEN, wx.ART_OTHER, isz))
         fileidx = il.Add(wx.ArtProvider_GetBitmap(wx.ART_REPORT_VIEW, wx.ART_OTHER, isz))
         #smileidx = il.Add(images.getSmilesBitmap())

         self.fldridx = fldridx
         self.fldropenidx = fldropenidx
         self.fileidx = fileidx

         self.tree.SetImageList(il)
         self.il = il

         # NOTE: For some reason tree items have to have a data object in
         # order to be sorted. Since our compare just uses the labels
         # we don't need any real data, so we'll just use None below for
         # the item data.

         self.root = self.tree.AddRoot("The Root Item")
         data = 0
         self.tree.SetPyData(self.root, data)
         self.tree.SetItemImage(self.root, fldridx, wx.TreeItemIcon_Normal)
         self.tree.SetItemImage(self.root, fldropenidx, wx.TreeItemIcon_Expanded)

         '''
         for x in range(15):
             child = self.tree.AppendItem(self.root, "Item %d" % x)
             self.tree.SetPyData(child, None)
             self.tree.SetItemImage(child, fldridx, wx.TreeItemIcon_Normal)
             self.tree.SetItemImage(child, fldropenidx, wx.TreeItemIcon_Expanded)
             for y in range(5):
                 last = self.tree.AppendItem(child, "item %d-%s" % (x, chr(ord("a")+y)))
                 self.tree.SetPyData(last, None)
                 self.tree.SetItemImage(last, fldridx, wx.TreeItemIcon_Normal)
                 self.tree.SetItemImage(last, fldropenidx, wx.TreeItemIcon_Expanded)
                 for z in range(5):
                     item = self.tree.AppendItem(last, "item %d-%s-%d" % (x, chr(ord("a")+y), z))
                     self.tree.SetPyData(item, None)
                     self.tree.SetItemImage(item, fileidx, wx.TreeItemIcon_Normal)
                     self.tree.SetItemImage(item, fileidx, wx.TreeItemIcon_Selected)
         '''

         self.tree.Expand(self.root)

         wx.EVT_TREE_ITEM_EXPANDED (self, tID, self.OnItemExpanded)
         wx.EVT_TREE_ITEM_COLLAPSED (self, tID, self.OnItemCollapsed)
         wx.EVT_TREE_SEL_CHANGED (self, tID, self.OnSelChanged)
         wx.EVT_TREE_BEGIN_LABEL_EDIT(self, tID, self.OnBeginEdit)
         wx.EVT_TREE_END_LABEL_EDIT (self, tID, self.OnEndEdit)
         wx.EVT_TREE_ITEM_ACTIVATED (self, tID, self.OnActivate)

         wx.EVT_LEFT_DCLICK(self.tree, self.OnLeftDClick)
         wx.EVT_RIGHT_DOWN(self.tree, self.OnRightClick)
         wx.EVT_RIGHT_UP(self.tree, self.OnRightUp)

     def AddItem(self,parent,label,data):
         child = self.tree.AppendItem(parent, label)
         t = type(data)
         #self.tree.SetPyData(child, None)
         self.tree.SetItemText(child, label)
         self.tree.SetPyData(child, None)
         #if dictionary or list, continue
         if t is types.DictType:
             self.tree.SetItemImage(child, self.fldridx, which = wx.TreeItemIcon_Normal)
             self.tree.SetItemImage(child, self.fldropenidx, which = wx.TreeItemIcon_Expanded)
             for (key,value) in data.items():
                 self.AddItem(child,key,value)
         elif t in (types.ListType,types.TupleType):
             self.tree.SetItemImage(child, self.fldridx, which = wx.TreeItemIcon_Normal)
             self.tree.SetItemImage(child, self.fldropenidx, which = wx.TreeItemIcon_Expanded)
             count = 0
             for value in data:
                 self.AddItem(child,str(count),value)
                 count+=1
         else: #unknown type or non-expandable singleton
             try:
                 self.tree.SetItemText(child, str(data), 2)
             except:
                 pass
             self.tree.SetItemImage(child, self.fileidx, which = wx.TreeItemIcon_Normal)
             self.tree.SetItemImage(child, self.fileidx, which = wx.TreeItemIcon_Selected)

     def OnRightClick(self, event):
         pt = event.GetPosition();
         item, flags = self.tree.HitTest(pt)
         #self.log.WriteText("OnRightClick: %s, %s, %s\n" %
         # (self.tree.GetItemText(item), type(item), item.__class__))
         self.tree.SelectItem(item)

     def OnRightUp(self, event):
         pt = event.GetPosition();
         item, flags = self.tree.HitTest(pt)
         #self.log.WriteText("OnRightUp: %s (manually starting label edit)\n"
         # % self.tree.GetItemText(item))
         self.tree.EditLabel(item)

     def OnBeginEdit(self, event):
         # show how to prevent edit...
         if self.tree.GetItemText(event.GetItem()) == "The Root Item":
             #wx.Bell()
             # Lets just see what's visible of its children
             cookie = 0
             root = event.GetItem()
             (child, cookie) = self.tree.GetFirstChild(root, cookie)
             while child.IsOk():
                 #self.log.WriteText("Child [%s] visible = %d" %
                 # (self.tree.GetItemText(child),
                 # self.tree.IsVisible(child)))
                 (child, cookie) = self.tree.GetNextChild(root, cookie)

             event.Veto()

     def OnEndEdit(self, event):
         #self.log.WriteText("OnEndEdit\n")
         # show how to reject edit, we'll not allow any digits
         for x in event.GetLabel():
             if x in string.digits:
                 #self.log.WriteText("You can't enter digits...\n")
                 event.Veto()
                 return

     def OnLeftDClick(self, event):
         pt = event.GetPosition();
         item, flags = self.tree.HitTest(pt)
         #self.log.WriteText("OnLeftDClick: %s\n" % self.tree.GetItemText(item))
         parent = self.tree.GetItemParent(item)
         self.tree.SortChildren(parent)
         event.Skip()

     def OnSize(self, event):
         w,h = self.GetClientSizeTuple()
         self.tree.SetDimensions(0, 0, w, h)

     def OnItemExpanded(self, event):
         item = event.GetItem()
         #self.log.WriteText("OnItemExpanded: %s\n" % self.tree.GetItemText(item))

     def OnItemCollapsed(self, event):
         item = event.GetItem()
         #self.log.WriteText("OnItemCollapsed: %s\n" % self.tree.GetItemText(item))

     def OnSelChanged(self, event):
         self.item = event.GetItem()
         #self.log.WriteText("OnSelChanged: %s\n" % self.tree.GetItemText(self.item))
         if wx.Platform == '__WXMSW__':
             #self.log.WriteText("BoundingRect: %s\n" %
             # self.tree.GetBoundingRect(self.item, True))
             pass
         #items = self.tree.GetSelections()
         #print map(self.tree.GetItemText, items)
         event.Skip()

     def OnActivate(self, event):
         #self.log.WriteText("OnActivate: %s\n" % self.tree.GetItemText(self.item))
         pass

     def Expand(self):
         self.tree.Expand(self.root)

#---------------------------------------------------------------------------

class InfoPanel(wx.Panel):
     def __init__(self, parent):
         # Use the WANTS_CHARS style so the panel doesn't eat the Return key.
         wx.Panel.__init__(self, parent, -1, style=wx.WANTS_CHARS)

#---------------------------------------------------------------------------

class MySplitter(wx.SplitterWindow):
     def __init__(self, parent, ID):
         wx.SplitterWindow.__init__(self, parent, ID)
         wx.EVT_SPLITTER_SASH_POS_CHANGED(self, self.GetId(), self.OnSashChanged)
         wx.EVT_SPLITTER_SASH_POS_CHANGING(self, self.GetId(), self.OnSashChanging)

     def OnSashChanged(self, evt):
         # uncomment this to not allow the change
         #evt.SetSashPosition(-1)
         pass

     def OnSashChanging(self, evt):
         # uncomment this to not allow the change
         #evt.SetSashPosition(-1)
         pass

#---------------------------------------------------------------------------

#---------------------------------------------------------------------------

class Frame(wx.Frame):
     """Frame class."""

     def __init__(self, parent=None, id=-1, title='PSV',
                  pos=wx.DefaultPosition, size=(400, 400)):
         """Create a Frame instance."""
         wx.Frame.__init__(self, parent, id, title, pos, size)

         self.MakeMenuBar()
         #self.MakeToolBar()
         self.MakeWindows()
         #self.treepanel = TestPanel(self)
         self.treepanel = TestTreeCtrlPanel(self.panel1)
         #self.infopanel = InfoPanel(self)

         self.MakeStatusbar()

         self.stashlist = {}

## General Initializers

     def MakeWindows(self):
         splitter = MySplitter(self, -1)

         panel1 = wx.Window(splitter, -1, size=wx.DefaultSize)
         #panel1.SetBackgroundColour(wx.RED)
         #wx.StaticText(panel1, -1, "Panel One", wx.Point(5,5)).SetBackgroundColour(wx.RED)

         panel2 = wx.Window(splitter, -1, size=wx.DefaultSize)
         #panel2.SetBackgroundColour(wx.BLUE)
         #wx.StaticText(panel2, -1, "Panel Two", wx.Point(5,5)).SetBackgroundColour(wx.BLUE)

         splitter.SetMinimumPaneSize(20)
         splitter.SplitVertically(panel1, panel2, 200)

         self.panel1 = panel1
         self.panel2 = panel2
         print panel1.GetSize()
         print panel2.GetSize()
         self.splitter = splitter

     def MakeMenuBar(self):
         self.MainMenu = wx.MenuBar()
         self.AddMenus(self.MainMenu)
         self.SetMenuBar(self.MainMenu)

     def MakeStatusbar(self):
         self.sb = wx.StatusBar(self, -1)
         #self.sb.SetFieldsCount(3)
         self.sb.sizeChanged = False
         #EVT_SIZE(self.sb, self.OnSize)
         #EVT_IDLE(self.sb, self.OnIdle)
         self.sb.SetStatusText("Welcome to the Python Stash Viewer.", 0)
         self.SetStatusBar(self.sb)

## Init Menus

     # override this to add more menus
     def AddMenus(self, menu):
         self.AddFileMenu(menu)
         #self.AddEditMenu(menu)
         self.AddHelpMenu(menu)

     def AddMenuItem(self, menu, itemText, itemDescription, itemHandler):
         menuId = wx.NewId()
         menu.Append(menuId, itemText, itemDescription)
         wx.EVT_MENU(self, menuId, itemHandler)
         return menuId

     def AddFileMenu(self, menu):
         fileMenu = wx.Menu()
         self.AddMenuItem(fileMenu, '&Open\tCtrl-O', 'Open File', self.OnOpenFile)
         self.AddMenuItem(fileMenu, '&Save File\tCtrl-S', 'Save File', self.OnSaveFile)
         self.AddMenuItem(fileMenu, 'E&xit\tAlt-F4', 'Exit', self.OnFileExit)
         menu.Append(fileMenu, 'File')

     def AddEditMenu(self, menu):
         editMenu = wx.Menu()
         #self.AddMenuItem(editMenu, 'Cut\tCtrl-X', 'Cut', self.edl.OnCutSelection)
         #self.AddMenuItem(editMenu, '&Copy\tCtrl-C', 'Copy', self.edl.OnCopySelection)
         #self.AddMenuItem(editMenu, 'Paste\tCtrl-V', 'Paste', self.edl.OnPaste)
         menu.Append(editMenu, 'Edit')

     def AddHelpMenu(self, menu):
         helpMenu = wx.Menu()
         self.AddMenuItem(helpMenu, 'About', 'About the program', self.OnHelpAbout)
         menu.Append(helpMenu, 'Help')

## Event handlers

     def SetStatus(self, text=None):
         self.sb.SetStatusText(text, 0)

     def OnCloseWindow(self, event):
         #check each stash for modification
         self.OnSaveAll()
         self.Destroy()

     def OnOpenFile(self, event):
         '''open file'''

         #acquire and verify input file
         dlg = wx.FileDialog(self, "Choose a file", os.getcwd(), "", "All files (*.*)|*.*", wx.OPEN)
         if dlg.ShowModal() == wx.ID_OK:
             path = dlg.GetPath()
             filename = dlg.GetFilename()
         else:
             return False

         try:
             newstash = stash(filename)
             self.SetStatus('loaded '+filename)#str(len(newstash.data)))
         except Exception, e:
             self.SetStatus('unable to load stash: '+str(e))
             return

         self.AddStash(newstash,path,filename)
         self.treepanel.Expand()

     def AddStash(self, s, p, f):
         '''reflects the additional stash in the tree list'''
         self.stashlist[p] = {'filename':f,'modified':False,'stash':s}
         self.treepanel.AddItem(self.treepanel.root,f,s.data)

     def OnSaveFile(self, event):
         self.OnSaveAll()
         pass

     def SaveFile(self, name):
         '''saves a single stash file'''
         print 'saving',name
         self.stashlist[name]['modified'] = False
         pass

     def OnSaveAll(self, event=None):
         '''tries to save all modified stash files'''
         for (name,data) in self.stashlist.items():
             #save unmodified
             if data['modified'] is True:
                 dlg = wx.MessageBox(parent=self, message = "Save file "+name+"?", caption = "Save", style = wx.YES_NO)
                 if dlg.ShowModal() == wx.ID_YES:
                     self.SaveFile(name)

     def OnFileExit(self, event):
         self.OnCloseWindow(event)

     def OnHelpAbout(self, event):
         dlg = wx.MessageDialog(self, ABOUT_TEXT, 'About PSV', wx.OK | wx.ICON_INFORMATION)
         dlg.ShowModal()
         dlg.Destroy()

class App(wx.App):
     """Application class."""

     def OnInit(self):
         self.frame = Frame()
         self.frame.Show()
         self.SetTopWindow(self.frame)
         return True

if __name__ == '__main__':
     app = App()
     app.MainLoop()

Alex Zeiger wrote:

I've created a splitterwindow, with a treectrl panel in the first window. The panel doesn't fill up the entire window using wx.DefaultSize, and refuses to do otherwise. I tried simply setting it to the size of the parent, but GetSize() returns zero! Is that a bug? How can there be a visible window with zero size?

How can you make a panel fill up a window?

I imagine the panel is filling the panel, but the tree control isn't. What I would suggest is adding a sizer to the panel, then add the tree control to the sizer.

On the matter of size, you won't know the size of the panel until the UI is completely built, so in order to trap that properly, you need to add an EVT_SIZE handler, and in that handler you get the size of the panel and do your adjustment. Not that I think this will be necessary - most likely the sizer will do everything you need.

# from memory: might need a few tweaks
class myPanel(wx.Panel)
   def __init__(self, parent):
     wx.Panel.__init__(self, parent, -1)

     self.sizer = wx.BoxSizer(wx.HORIZONTAL)

     self.Tree = wx.TreeCtrl(blah blah)

     self.sizer.Add(self.Tree, 1, flags=wx.ALL | wx.EXPAND)

     self.SetSizer(self.sizer)
     self.sizer.Fit(self)

     # and all your other stuff too

... 'For the diet conscious, Sprint now makes the ominous offer to
     "take 50 percent off the person you call the most."'

That runs, but the effect is the same.

Jeff Grimmett wrote:

···

Alex Zeiger wrote:

>

I imagine the panel is filling the panel, but the tree control isn't. What I would suggest is adding a sizer to the panel, then add the tree control to the sizer.

On the matter of size, you won't know the size of the panel until the UI is completely built, so in order to trap that properly, you need to add an EVT_SIZE handler, and in that handler you get the size of the panel and do your adjustment. Not that I think this will be necessary - most likely the sizer will do everything you need.

# from memory: might need a few tweaks
class myPanel(wx.Panel)
  def __init__(self, parent):
    wx.Panel.__init__(self, parent, -1)

    self.sizer = wx.BoxSizer(wx.HORIZONTAL)

    self.Tree = wx.TreeCtrl(blah blah)

    self.sizer.Add(self.Tree, 1, flags=wx.ALL | wx.EXPAND)

    self.SetSizer(self.sizer)
    self.sizer.Fit(self)

    # and all your other stuff too

It also seems to disable manipulation of the tree. With the sizer, I am unable to select, expand, or edit the labels of tree items.

Alex Zeiger wrote:

···

That runs, but the effect is the same.

Alex Zeiger wrote:

That runs, but the effect is the same.

Well, let's be more specific then. This is an extract of code I am currently working with, and it works exactly as it should. Maybe a clue can be found within it as to what's being missed. It's actually quite simple so I'm sure something will jump out. I've pared out a bunch of extraneous stuff to make it more readable. The app is a wx.Frame with a top level panel with sizer, within that sizer is my splitter, and within its left pane is a panel with sizer, and in that is the tree. The right panel of the splitter window just has a blank panel since what's over there is of no concern for this example.

I swear on my K&R, this works :slight_smile:

The top level frame:

class MainFrame(wx.Frame):
     def __init__(self):
         wx.Frame.__init__(self, None, -1, ' My Frame'
             style=wx.DEFAULT_FRAME_STYLE)

         # Create a status bar
         self.status = self.CreateStatusBar()
         # Top level window
         self.panel = wx.Panel(self, -1)

         p.sizer = wx.BoxSizer(wx.VERTICAL)

         p.contentPane = wx.SplitterWindow(
      p, -1, style=wx.SP_3D|wx.WANTS_CHARS)

         self.tree = TreePanel(p.contentPane)
         self.news = wx.Panel(p.contentPane, -1) # Dummy panel

         # Create our working areas. Don't set position yet. We don't know
         # the actual size of the window until we get a SIZE event.
         p.contentPane.SplitVertically(p.tree, p.news)

         p.sizer.Add(p.contentPane, border=3, proportion=1, flag = wx.ALL | wx.EXPAND)

         p.SetSizer(self.sizer)
         p.sizer.Fit(p)

         # Set up our event traps
         self.Bind(wx.EVT_CLOSE, self.Shutdown)

Tree panel:

class TreePanel(wx.Panel):
     def __init__(self, parent):
         wx.Panel.__init__(self, parent)

         self.sizer = wx.BoxSizer(wx.VERTICAL)

         self.Tree = wx.TreeCtrl(self, -1,
             style = wx.TR_HAS_BUTTONS | wx.TR_ROW_LINES | wx.TR_LINES_AT_ROOT )

         self.sizer.Add(self.Tree, border=0, proportion=1, flag = wx.ALL | wx.EXPAND )

         self.SetSizer(self.sizer)
         self.sizer.Fit(self)

... "I said $150 Million in *SNAPPLE*, you idiot!" -- B. Gates