Ultimatelistctrl header checkbox partial check

I have a ultimatelistctrl which have checkbox in the header of the column, When I check the checkbox then all the checkbox in that column are gets checked, but when I uncheck any of the checkbox in the column, then checkbox in the column header remains selected. As per the standard, checkbox in the header must gets unchecked when any of the checkbox in the column is not checked. I’m new to the wxpython and any help would be really appreciated. @Robin , @driscollis, @Andrea_Gavana need your help here.

oh dear me, you forgot the @pope :rofl:

replace line 5606 by

rect = wx.Rect(theX + HEADER_OFFSET_X, HEADER_OFFSET_Y + int((h - 4 - iy)/2), ix, iy)

Still not working as expected, still the checkbox in header remains checked even if I there is one unchecked checkbox in the column image

I assume that the functionality relies on the style ULC_AUTO_CHECK_PARENT

Looking in ultimatelistctrl.py that style is set to 0x1000000 and referenced in several docstrings but doesn’t appear to be used anywhere?

well, the red light doesn’t always keep what it promises you from the outside :hot_face: (it looks as though it is work-in-progress what you expect)

The following workaround depends on EVT_LIST_ITEM_SELECTED being triggered before EVT_LIST_ITEM_CHECKED which appears to be the case on my PC using Python 3.10.12 + wxPython 4.2.1 gtk3 (phoenix) wxWidgets 3.2.2.1 on Linux Mint 21.2

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

class MyFrame(wx.Frame):
    def __init__(self, parent):
        wx.Frame.__init__(self, parent)
        agw_style = (wx.LC_REPORT | wx.LC_VRULES | wx.LC_HRULES | wx.LC_SINGLE_SEL |
                     ULC.ULC_AUTO_CHECK_CHILD | ULC.ULC_AUTO_CHECK_PARENT)
        self.ulc = ULC.UltimateListCtrl(self, -1, agwStyle=agw_style, size=(640, 480))

        self.Bind(ULC.EVT_LIST_ITEM_CHECKED,  self.OnItemChecked, self.ulc)
        self.Bind(ULC.EVT_LIST_ITEM_SELECTED, self.OnItemClicked, self.ulc)

        self.populateList()

        self.clicked_col = -1


    def populateList(self):
        info = ULC.UltimateListItem()
        info._mask = wx.LIST_MASK_TEXT | wx.LIST_MASK_FORMAT | ULC.ULC_MASK_WIDTH | ULC.ULC_MASK_CHECK
        info._format = 0
        info._kind = 1
        info._text = "Column 0"
        info._width = 120
        self.ulc.InsertColumnInfo(0, info)
        info = ULC.UltimateListItem()
        info._mask = wx.LIST_MASK_TEXT | wx.LIST_MASK_FORMAT | ULC.ULC_MASK_WIDTH | ULC.ULC_MASK_CHECK
        info._format = 0
        info._kind = 1
        info._text = "Column 1"
        info._width = 120
        self.ulc.InsertColumnInfo(1, info)
        for r in range(8):
            label = f"Col 0, Item {r}"
            self.ulc.InsertStringItem(r, label, it_kind=1)
            label = f"Col 1, Item {r}"
            self.ulc.SetStringItem(r, 1, label, it_kind=1)


    def OnItemClicked(self, event):
        self.clicked_col = event.m_col


    def OnItemChecked(self, _event):
        num_checked = self.ulc.GetCheckedItemCount(self.clicked_col)
        num_items = self.ulc.GetItemCount()

        info = self.ulc.GetColumn(self.clicked_col)

        if num_checked == num_items:
            # All checked
            info.Check(True)
        else:
            # Not all checked
            info.Check(False)

        self.ulc.SetColumn(self.clicked_col, info)


if __name__ == '__main__':
    app = wx.App()
    frame = MyFrame(None)
    frame.Show()
    app.MainLoop()
1 Like

Thank you @RichardT , It worked !! but its not working properly in ULC.ULC_VIRTUAL mode, any suggestions on that?

@RichardT , please suggest for ULC.ULC_VIRTUAL mode

I can’t remember ever needing to have to use virtual mode with an UltimateListCtrl before. I would need to do some research on the topic and then investigate what consequences using checkboxes would have. This would take some time which, unfortunately, I don’t have very much of at the moment - sorry.

virtual mode & check boxes are a contradiction, I think :rofl:

put this

        item.Check(checked)
        self.SetItem(item)
        self.RefreshLine(item._itemId)

        if self.HasAGWFlag(ULC_AUTO_CHECK_PARENT) and\
                item.GetKind() == 1:        # check box like item
            col = item.GetColumn()
            info = self.GetColumn(col)
            if self.GetCheckedItemCount(col) == self.GetItemCount():
                info.Check(True)
            else:
                info.Check(False)
            self.SetColumn(col, info)

        if not sendEvent:
            return

at approximately line 9029 into ultimatelistctrl.py (observe the surrounding) and you get @RichardT 's workaround as a workin :rofl:

1 Like

A PR to implement @da-dada’s code change has now been merged to the master branch in the wxPython repo.

well, Scotty must be living next door to you :joy: (but the bad return code on Windows with Python 3.12 he is still working on, expecting sip being the devil, although importing PyQt does’t cause any problem :innocent:)

Well, dear Scotty your responses have been the same, so too increment a faithful implementation, Scotty has to do something for us…? Hmmm Scotty? Appalling isn’t it…