Search code examples
pythonwxpythoncolor-picker

ColourPickerCtrl in a ListCtrl


Problem: I have a wx.ListCtrl in which I want to include a color picker. So, given a list such as in this image: ListCtrl

What I want to get is something like this:

enter image description here

In which the black square element is the wx.ColorPickerCtrl. I've looked in ListCtrl methods and couldn't find anything. I've also looked in UltimateListCtrl but didn't find any method either.

This is my code so far:

import wx
import wx.xrc


class MyFrame1 ( wx.Frame ):

    def __init__( self, parent ):
        wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = wx.EmptyString, pos = wx.DefaultPosition, size = wx.Size( 500,300 ), style = wx.DEFAULT_FRAME_STYLE|wx.TAB_TRAVERSAL )

        self.SetSizeHintsSz( wx.DefaultSize, wx.DefaultSize )

        bSizer2 = wx.BoxSizer( wx.VERTICAL )

        self.m_panel2 = wx.Panel( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL )
        bSizer3 = wx.BoxSizer( wx.VERTICAL )

        self.m_listCtrl9 = wx.ListCtrl( self.m_panel2, style=wx.LC_REPORT| wx.LC_HRULES | wx.LC_SINGLE_SEL | wx.BORDER_SUNKEN)
        self.m_listCtrl9.InsertColumn(0, 'Something')
        self.m_listCtrl9.InsertColumn(1, 'Description')
        self.m_listCtrl9.InsertColumn(2, 'Color ', width=125)

        for i in range(0,20):
            self.m_listCtrl9.InsertStringItem(0, "212343" + str(i))


        bSizer3.Add( self.m_listCtrl9, 0, wx.ALL|wx.EXPAND, 5 )

        self.m_staticline4 = wx.StaticLine( self.m_panel2, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL )
        bSizer3.Add( self.m_staticline4, 0, wx.EXPAND |wx.ALL, 5 )

        self.m_panel2.SetSizer( bSizer3 )
        self.m_panel2.Layout()
        bSizer3.Fit( self.m_panel2 )
        bSizer2.Add( self.m_panel2, 1, wx.EXPAND |wx.ALL, 5 )

        self.SetSizer( bSizer2 )
        self.Layout()

        self.Centre( wx.BOTH )

def main():

    app = wx.App(False)
    f = MyFrame1(None)
    f.Show()
    app.MainLoop()    


if __name__ == '__main__':
    main()

I was thinking maybe there is a obvious way to do it because it seems simple, but I don't know how to do it, any suggestions?

Thanks in advance.


Solution

  • You surely need UltimateListCtrl to achieve desired behaviour. It has a SetItemWindow method, which can insert a control to the ListCtrl. To make it work, ensure that the style of UltimateListCtrl includes both wx.LC_REPORT and ulc.ULC_HAS_VARIABLE_ROW_HEIGHT. This should do the trick:

    import wx.lib.agw.ultimatelistctrl as ulc
    
    class MyFrame1 ( wx.Frame ):
        def __init__( self, parent ):
            ...
            self.m_listCtrl9 = ulc.UltimateListCtrl( self.m_panel2, agwStyle=wx.LC_REPORT|ulc.ULC_HAS_VARIABLE_ROW_HEIGHT)
            ...
            self.color_pickers = []
            for i in range(20):
                idx = self.m_listCtrl9.InsertStringItem(0, "212343" + str(i))
                color_picker = wx.ColourPickerCtrl(self.m_listCtrl9, -1)
                self.m_listCtrl9.SetItemWindow(idx, 2, color_picker)
                self.color_pickers.append(color_picker)
    

    This yields the following result: enter image description here