DataViewListCtrl with color column not editable

Hi there,
I am using wxpython 4.2.4 with pythpon 3.14 on windows. I plan to convince my company to use wxpython for rapid prototyping of advanced GUIs.
Right now, I am struggeling with getting a DataViewListCtrl to have an editable column that shows colors. I can show the colors by using a ColorRenderer derived from DataViewCustomRenderer, but I can’t get the cells to be editable. The ActivateCell function in my renderer is not getting called, though I have instantiated my renderer with the mode dv.DATAVIEW_CELL_EDITABLE, and also provided a custom variantType.
What am I doing wrong? Here is my code:

import wx
import wx.dataview as dv

class DataApp(wx.App):

    def __init__(self):
        wx.App.__init__(self)
        frame = wx.Frame(None, id=wx.ID_ANY, title="Data frame")
        panel = wx.Panel(frame, id = wx.ID_ANY)
        sizer = wx.FlexGridSizer(1, wx.Size(6,6))
        model = dv.DataViewListStore()
        view = dv.DataViewListCtrl(panel)
        view.AppendTextColumn("First name",0)
        view.AppendTextColumn("Last name",1)
        view.AppendColumn(dv.DataViewColumn("Age",NumberRenderer(),2))
        view.AppendColumn(dv.DataViewColumn("Color",ColorRenderer(),3), "color")

        view.AssociateModel(model)
        model.AppendItem(["John","Doered",20,'#ff0000'])
        model.AppendItem(["Jane","Doegreen",21,'#00ff00'])
        model.AppendItem(["Jim","Doeblue","33",'#0000ff'])
        sizer.AddGrowableCol(0, proportion=1)
        sizer.AddGrowableRow(0, proportion=1)
        sizer.Add(view, flag = wx.ALL | wx.EXPAND, border=6)
        panel.SetSizerAndFit(sizer)
        frame.Show()

class ColorRenderer(dv.DataViewCustomRenderer):
    def __init__(self):
        super().__init__(mode = dv.DATAVIEW_CELL_EDITABLE)
        self.size = wx.Size(16,16)

    def GetSize(self):
        return self.size;
        
    def IsCompatibleVariantType(self, variant):
        return variant in ("string", "color")

    def SetValue(self, value):
        print("Setting value to " + value)
        self.value = value;
        return True
    
    def ActivateCell(self, cell, model, item, col, mouseEvent):
        print(f"Cell activated in column {col} with value: {self.value}")
        return True  # Prevent default editing
    
    def Render(self, cell, dc, state):
        hexString = self.value
        dc.SetBrush(wx.Brush(wx.Colour(hexString),wx.BRUSHSTYLE_SOLID))
        dc.DrawRectangle(cell)
        return True
    
class NumberRenderer(dv.DataViewTextRenderer):
    def __init__(self):
        super().__init__()

    def IsCompatibleVariantType(self, variant):
        return variant in ("long", "double", "datetime", "string")
    
if __name__ == "__main__":
    app = DataApp()
    app.MainLoop()


Hello again, ok, almost there. After studying the wxpython demo codes, I added methods in my renderer to create editors and to return their values. Now, I can render and edit colors, but only if I handle them as hex code strings. If I try to handle them as instances of wx.Colour, they are not rendered, though the editor (a wx.ColourPickerCtrl) is still displayed and is operational, but the Render method is never called if the value is a wx.Colour and not a hex string. I guess that this is due to a wrong variantType. I tried “any”, “variant” and “object” for both renderers/DataViewColumns. The HexCodeRenderer always renders the color, the RealColorRenderer never does this.Is there a way to change that? What am I doing wrong?
Here is my updated code:

import wx
import wx.dataview as dv

class DataApp(wx.App):

    def __init__(self):
        wx.App.__init__(self)
        frame = wx.Frame(None, id=wx.ID_ANY, title="Data frame")
        panel = wx.Panel(frame, id = wx.ID_ANY)
        sizer = wx.FlexGridSizer(1, wx.Size(6,6))
        model = dv.DataViewListStore()
        view = dv.DataViewListCtrl(panel)
        view.AppendTextColumn("First name",0)
        view.AppendTextColumn("Last name",1)
        view.AppendColumn(dv.DataViewColumn("Age",NumberRenderer(),2))
        view.AppendColumn(dv.DataViewColumn("Color as hex code",HexCodeRenderer(),3), "any")
        view.AppendColumn(dv.DataViewColumn("Real color",RealColorRenderer(),4), "any")

        view.AssociateModel(model)
        model.AppendItem(["John","Doered",20,'#ff0000',wx.Colour.Red])
        model.AppendItem(["Jane","Doegreen",21,'#00ff00',wx.Colour.Green])
        model.AppendItem(["Jim","Doeblue","33",'#0000ff', wx.Colour.Blue])
        sizer.AddGrowableCol(0, proportion=1)
        sizer.AddGrowableRow(0, proportion=1)
        sizer.Add(view, flag = wx.ALL | wx.EXPAND, border=6)
        panel.SetSizerAndFit(sizer)
        frame.Show()


class ColorRenderer(dv.DataViewCustomRenderer):
    def __init__(self):
        super().__init__(mode = dv.DATAVIEW_CELL_EDITABLE)
        self.size = wx.Size(16,16)
        self.value = None

    def GetSize(self):
        return self.size;
        
    def IsCompatibleVariantType(self, variant):
        return variant in ("any","string","variant","object")

    def SetValue(self, value):
        print("Setting value to " + str(value)+" of type " + str(type(value)))
        self.value = value;
        return True
    
    def GetValue(self):
        return self.value
    
    def ActivateCell(self, cell, model, item, col, mouseEvent):
        print(f"Cell activated in column {col} with value: {self.value}")
        return True  # Prevent default editing
    
    def Render(self, cell, dc, state):
        print(str(type(self)) + " rendering value " + str(self.value)+" of type " + str(type(self.value)))
        dc.SetBrush(wx.Brush(self.value,wx.BRUSHSTYLE_SOLID))
        dc.DrawRectangle(cell)
        return True

    def CreateEditorCtrl(self, parent, labelRect, value):
        print(str(type(self)) + " creating editor")
        ctrl = wx.ColourPickerCtrl(parent,
                           colour=wx.Colour(value),
                           pos=labelRect.Position,
                           size=labelRect.Size)
        return ctrl

class HexCodeRenderer(ColorRenderer):
    def __init__(self):
        super().__init__()

    def GetValueFromEditorCtrl(self, editor):
        print(str(type(self)) + " getting value from editor " + str(type(editor)))
        value = editor.GetColour().GetAsString(wx.C2S_HTML_SYNTAX)
        print ("GetValueFromEditorCtrl.value " + str(value))
        self.value = value
        return True, value

class RealColorRenderer(ColorRenderer):
    def __init__(self):
        super().__init__()

    def GetValueFromEditorCtrl(self, editor):
        print(str(type(self)) + " getting value from editor " + str(type(editor)))
        value = editor.GetColour()
        print ("GetValueFromEditorCtrl.value " + str(value))
        self.value = value
        return True, value
        
class NumberRenderer(dv.DataViewTextRenderer):
    def __init__(self):
        super().__init__()

    def IsCompatibleVariantType(self, variant):
        return variant in ("long", "double", "datetime", "string")
    
if __name__ == "__main__":
    app = DataApp()
    app.MainLoop()