[wxPython-users] Scrollbar help with DynamicSashWindow

Andrea Gavana andrea.gavana at gmail.com
Thu Mar 22 16:47:02 PDT 2007


Hi Danny,

On 3/22/07, Danny Shevitz wrote:
> Time for the next question. I have now put the TreeCtrl in a Panel. The
> size of the TreeCtrl is fixed, and the panel
> is sized to fit. The problem is that the trees can grow arbitrarily large.
> Is there a way to dynamically resize the
> tree/panel so that the tree fits itself without it's own scrollbar. I tri=
ed
> looking at
> GetVirtualSize, GetBestSize,GetBestVirtualSize,GetEffectiveMinSize, etc.f=
or
> the tree to find what
> virtual size it should be, but none of these methods seem to work.
>
> In summary, is there a dynamic way to find the virtual size of the tree, =
so
> that I can update the physical size
> to always be the same size? Would I need to re-Fit the Panel after this
> operation?

If I understand your question correctly, you could try the attached
file. Every time you expand/collapse a node, if the size of the
longest item does not fit (or it has too much space), the treectrl is
resized accordingly to avoid the horizontal scrollbars. The attached
file uses a splitterwindow to place the treectrl but it should be
trivial to use a panel + sizer + treectrl.
And, yes, try to call sizer.Layout() or panel.Layout() or
yourframe.SendSizeEvent() (as a last resource) to layout your
panel/tree configuration.

Hope this helps.

Andrea.

"Imagination Is The Only Weapon In The War Against Reality."
http://xoomer.virgilio.it/infinity77/
-------------- next part --------------
import wx

class MyFrame(wx.Frame):

    def __init__(self, parent, id=3Dwx.ID_ANY, title=3D"", pos=3Dwx.Default=
Position,
                 size=3Dwx.DefaultSize, style=3Dwx.DEFAULT_FRAME_STYLE, exp=
and=3D0):

        wx.Frame.__init__(self, parent, id, title, pos, size, style)

        self.splitter =3D wx.SplitterWindow(self, -1)
        =

        self.treectrl =3D wx.TreeCtrl(self.splitter, -1)
        self.panel =3D wx.Panel(self.splitter, -1)

        self.splitter.SplitVertically(self.treectrl, self.panel, 2000)

        self.PopulateTreeCtrl()
        self.ExpandItems(expand)

        self.CenterOnScreen()
        self.Show()
        =

        wx.CallLater(100, self.CalculateMaxItemSize)

        self.Bind(wx.EVT_TREE_ITEM_EXPANDED, self.OnItemExpandedCollapsed)
        self.Bind(wx.EVT_TREE_ITEM_COLLAPSED, self.OnItemExpandedCollapsed)
        =


    def PopulateTreeCtrl(self):

        self.treectrl.Freeze()
        root =3D self.treectrl.AddRoot("The root item")
        =

        for x in range(15):
            child =3D self.treectrl.AppendItem(root, "Item %d" % x)

            for y in range(5):
                last =3D self.treectrl.AppendItem(child, "item %d-%s" % (x,=
 chr(ord("a")+y)))

                for z in range(5):
                    item =3D self.treectrl.AppendItem(last,  "item %d-%s-%d=
" % (x, chr(ord("a")+y), z))

        self.treectrl.Thaw()
        =


    def ExpandItems(self, expand):

        root =3D self.treectrl.GetRootItem()
        self.treectrl.Expand(root)
        =

        if expand =3D=3D 0:
            # No expanding requested
            return

        elif expand =3D=3D 1:
            # expand first level of children
            child, cookie =3D self.treectrl.GetFirstChild(root)
            while child.IsOk():
                self.treectrl.Expand(child)
                child, cookie =3D self.treectrl.GetNextChild(root, cookie)
    =

        else:
            # Expand all children
            self.treectrl.ExpandAll()

        self.treectrl.EnsureVisible(root)


    def CalculateMaxItemSize(self):

        root =3D self.treectrl.GetRootItem()
        rect =3D self.treectrl.GetBoundingRect(root, True)

        # It looks like the space between the "+" and the node
        # rect occupies 4 pixels approximatively
        maxwidth =3D rect.x + rect.width + 4
        lastheight =3D rect.y + rect.height
        =

        if not self.treectrl.IsExpanded(root):
            return maxwidth

        maxwidth, lastheight =3D self.RecurseOnChildren(root, maxwidth)

        # Remember to add the size of the vertical scrollbar
        # if you have one (it appears when you have many items)
        scrollbarsize =3D 0
        if lastheight >=3D self.GetSize()[1]:
            scrollbarsize +=3D wx.SystemSettings_GetMetric(wx.SYS_HTHUMB_X)
            =

        self.SetSashPosition(maxwidth + scrollbarsize)
        =


    def RecurseOnChildren(self, item, maxwidth):
        =

        child, cookie =3D self.treectrl.GetFirstChild(item)

        while child.IsOk():

            rect =3D self.treectrl.GetBoundingRect(child, True)
            =

            # It looks like the space between the "+" and the node
            # rect occupies 4 pixels approximatively
            maxwidth =3D max(maxwidth, rect.x + rect.width + 4)
            lastheight =3D rect.y + rect.height
            =

            if self.treectrl.IsExpanded(child):
                maxwidth, lastheight =3D self.RecurseOnChildren(child, maxw=
idth)
            =

            child, cookie =3D self.treectrl.GetNextChild(item, cookie)

        return maxwidth, lastheight


    def SetSashPosition(self, maxwidth):

        self.Freeze()
        self.splitter.SetSashPosition(maxwidth)
        self.Thaw()


    def OnItemExpandedCollapsed(self, event):

        self.Freeze()
        self.CalculateMaxItemSize()
        self.Thaw()

        =

# Try changing this value to get different expanding behavior
# for the wx.TreeCtrl
expand =3D 1

def main():

    app =3D wx.PySimpleApp()
    frame =3D MyFrame(None, -1, "TreeCtrl Sample", size=3D(500, 400), expan=
d=3Dexpand)
    app.MainLoop()


if __name__ =3D=3D "__main__":
    main()

    =

    =

       =20


More information about the wxpython-users mailing list