Phoenix icon indicating copy to clipboard operation
Phoenix copied to clipboard

TreeListCtrl column width auto-size always sets small width values

Open brendan-simon-indt opened this issue 2 years ago • 4 comments

Operating system: Windows 10 wxPython version: 4.1.2a1.dev5310+af8cca51 Python version: CPython 3.9.12

Description of the problem:

Using python TreeListCtrl.SetColumnWidth( col, width=wx.LIST_AUTOSIZE ) always results in very small column widths (e.g. 16) regardless of content.

This also effects TreeListCtrl.SetColumnWidth( col, width=gizmos.LIST_AUTOSIZE_CONTENT_OR_HEADER ), and effectively only auto-sizes to the column header text.

TreeListCtrl.SetColumnWidth( col, width=wx.LIST_AUTOSIZE_USEHEADER ) works as expected.

Code Example (click to expand)
#!/usr/bin/env python3
# -*- coding: UTF-8 -*-

#!============================================================================

import wx

import wx.lib.gizmos as gizmos

#!============================================================================

class Test_TreeListCtrl( gizmos.TreeListCtrl ) :
    """
    EFD Unit TreeListCtrl.
    """

    def __init__(
        self,
        parent,
        id          : int   = wx.ID_ANY,
        ) -> None :

        super().__init__( parent, id )

        columns = ( 'Name', 'AbcdefghijklmnopqrstuvwxyZ', 'A', 'Blah' )
        for col_name in columns :
            self.AddColumn( col_name )

        self.SetMainColumn( 0 )

        root = self.root = self.AddRoot("Root")

        ct_type = 1     #! checkbox

        #!--

        group1 = self.AppendItem( root, "Group 1" )

        child2 = self.AppendItem( group1, "Item 10", ct_type=ct_type )
        self.SetItemText( child2, "ABCDEFGH", 1 )
        self.SetItemText( child2, "12345678", 2 )

        child2 = self.AppendItem( group1, "Item 11", ct_type=ct_type )
        self.SetItemText( child2, "ABCDEFGH", 1 )
        self.SetItemText( child2, "12345678", 2 )

        self.Expand( group1 )

        #!--

        group2 = self.AppendItem( root, "Group 2" )

        child2 = self.AppendItem( group2, "Item 22-----------------------------------X", ct_type=ct_type )
        self.SetItemText( child2, "ABCDEFGH-----------------------------------X", 1 )
        self.SetItemText( child2, "12345678-----------------------------------X", 2 )

        child2 = self.AppendItem( group2, "Item 21", ct_type=ct_type )
        self.SetItemText( child2, "ABCDEFGH", 1 )
        self.SetItemText( child2, "12345678", 2 )

        self.Expand( group2 )

        #! NOTE: can't expand a hidden root
        if not self.HasAGWFlag(gizmos.TR_HIDE_ROOT):
            self.Expand( root )

        #! --- autosize columns ---
        for col, _ in enumerate( columns ) :
            # self.SetColumnWidth( col, width=gizmos.LIST_AUTOSIZE_CONTENT_OR_HEADER )
            self.SetColumnWidth( col, width=wx.LIST_AUTOSIZE )
            # self.SetColumnWidth( col, width=wx.LIST_AUTOSIZE_USEHEADER )

    #!------------------------------------------------------------------------


#!============================================================================

class Test_Frame(wx.Frame):
    def __init__(self, *args, **kwds):
        kwds["style"] = kwds.get("style", 0) | wx.DEFAULT_FRAME_STYLE
        wx.Frame.__init__(self, *args, **kwds)
        self.SetSize((400, 220))
        self.SetTitle("frame")

        self.panel_1 = wx.Panel(self, wx.ID_ANY)

        sizer_1 = wx.BoxSizer(wx.VERTICAL)

        self.test_tree_list = Test_TreeListCtrl(self.panel_1, wx.ID_ANY)
        sizer_1.Add(self.test_tree_list, 1, wx.EXPAND, 0)

        self.panel_1.SetSizer(sizer_1)

        self.Layout()

#!============================================================================

class Test_App(wx.App):
    """
    EFD Service Applicaiton class.
    """

    def OnInit(self):
        self.frame = Test_Frame(None, wx.ID_ANY, "")
        self.SetTopWindow(self.frame)
        self.frame.Show()
        return True

#!============================================================================

if __name__ == "__main__":
    app = Test_App(0)
    app.MainLoop()

brendan-simon-indt avatar May 19 '22 02:05 brendan-simon-indt

GetItemWidth() seems to produce good numbers, so I assume it's something to do with traversing the child items of the tree in GetBestColumnWidth().

I reviewed the code and everything looks ok (to me).

The only thing that makes sense as to why GetBestColumnWidth() is return 10, is traversing the items is return None. i.e. GetFirstChild() (and probalby GetNextChild()) is returning None and therefore the default of 10 max(width, 10) is being returned.

brendan-simon-indt avatar May 19 '22 04:05 brendan-simon-indt

The problem is GetClientSize() is returning 16 for the width.

    def GetBestColumnWidth(self, column, parent=None):

        maxWidth, h = self.GetClientSize()

        ...

brendan-simon-indt avatar May 19 '22 05:05 brendan-simon-indt

Issue also seems to be also present in wxPython v4.1.1 (unless there is something wrong in the way I've coded things in my app).

brendan-simon-indt avatar May 19 '22 06:05 brendan-simon-indt

Ok, so I think it is red herring and misprogramming on my part !!

I was setting the contents of the tree in the __init__() method of my custom TreeListCtrl. This all happens before the frame calls Layout()

If I refactor adding the contents and setting column width into a populate() method, which is called after the frame Layout(), then things work better.

One note though is that the first column DOES NOT auto-size properly - it's not quite wide enough. I presume that is due to the tree expand/collapse controls and the optional checkboxes/radio-buttons, etc.

brendan-simon-indt avatar May 19 '22 11:05 brendan-simon-indt