DataViewListCtrl last column fixed size/non-resizable still takes all remaining space

wxPython on Windows

I want the last column of a DataViewLIstCtrl to have a fixed size, with remaining space spread out over all the other columns. Google results suggest this is accomplished by

  • Setting the last column width to a fixed amount (i.e. 100px) and removing the wxDATAVIEW_COL_RESIZABLE flag
  • Making all the other columns resizable

I did this but the last column still takes up all remaining space. Is this just a limitation of the Windows implementation?

I get the same result using wxPython 4.2.5 gtk3 (phoenix) wxWidgets 3.2.9 + Python 3.12.3 + Linux Mint 22.3.

I couldn’t see a way to get the behaviour you want using the DataViewListCtrl.

The UltimateListCtrl has a ULC_AUTOSIZE_FILL setting, but I could only get it to work on a single column.

Here is a simple example:

import wx
import wx.lib.agw.ultimatelistctrl as ULC

DATA = (
    ("aaaaa bbbbb ccccc ddddd eeeee fffff", "Red"),
    ("aaaaa bbbbb ccccc ddddd eeeee fffff ggggg", "Green"),
    ("aaaaa bbbbb ccccc ddddd eeeee fffff ggggg hhhhh", "Blue"),
)


class MyFrame(wx.Frame):
    def __init__(self, parent):
        wx.Frame.__init__(self, parent, -1, "ULC_AUTOSIZE_FILL Demo")
        self.SetSize(560, 300)
        agw_style = ULC.ULC_REPORT | ULC.ULC_VRULES | ULC.ULC_HRULES | ULC.ULC_SINGLE_SEL
        self.ulc = ULC.UltimateListCtrl(self, wx.ID_ANY, agwStyle=agw_style)

        self.ulc.InsertColumn(0, "Col 0")
        # This has no effect, only "Col 1" automatically resizes
        self.ulc.SetColumnWidth(0, ULC.ULC_AUTOSIZE_FILL)

        self.ulc.InsertColumn(1, "Col 1")
        # This works - the column fills the remaining 
        # space and resizes when the frame is resized
        self.ulc.SetColumnWidth(1, ULC.ULC_AUTOSIZE_FILL)
        
        self.ulc.InsertColumn(2, "Col 2")

        for i, (a, b) in enumerate(DATA):
            index = self.ulc.InsertStringItem(i, "Row %d" % i)
            self.ulc.SetStringItem(index, 1, a)
            self.ulc.SetStringItem(index, 2, b)

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.ulc, 1, wx.EXPAND)

        self.SetSizer(sizer)
        self.Layout()


if __name__ == "__main__":
    app = wx.App(0)
    frame = MyFrame(None)
    frame.Show()
    app.MainLoop()

vokoscreenNG-2026-03-09_14-15-36

While not precisely what you were asking for, I also found this behavior (annoying). I solved it with a custom size event. Here’s the gist:

import wx
import wx.dataview as dv

class FileListPanel(wx.Panel):
    """Docstring for FileListPanel"""
    def __init__(self, parent, *args, **kwds):
        error_file = kwds.pop('file')
        super().__init__(parent, *args, **kwds)  # Call the parent class's constructor

        list_sizer = wx.BoxSizer(wx.VERTICAL)

        self.file_list = dv.DataViewListCtrl(self)
        list_sizer.Add(self.file_list, 1, wx.EXPAND, 0)

        file_col = self.file_list.AppendTextColumn('File')
        file_col.SetResizeable(True)
        file_col.SetMinWidth(200)
        count_col = self.file_list.AppendTextColumn('Embedded')
        count_col.SetWidth(80)
        count_col.SetResizeable(False)

        self.SetSizer(list_sizer)
        self.Layout()
        self.file_list.Bind(wx.EVT_SIZE, self.on_size)

    def on_size(self, evt) -> None:
        evt.Skip()
        self.size_columns()

    def size_columns(self) -> None:
        desired_count_width = 100
        size = self.file_list.GetSize()
        file_col, count_col = self.file_list.GetColumns()
        file_col.SetWidth(size.width - desired_count_width)
        count_col.SetWidth(desired_count_width)

Joe