ListCtrl Icon Transparency - Windows Bug?

I am trying to use icons in a ListCtrl report view with Windows.
I have managed to display the icons in whichever column I like (thanks to several posts from Robin which discuss the issue with Windows displaying always the icons in the first column).

However, I cannot get the icons to display with transparency, the background is always white.
Is this another bug in Windows ?

Are there any suggestions for a work-around?
The option I have is to put the icon in the first column so it doesnt break the row colour in the middle…

This is what I want versus what I get today in Windows…
Icon-Final Icon-Orig

I tried also with a PNG I created (which displays with a transparent background in an image viewer)
Warning

Here is my example code:

import wx

class MyFrame(wx.Frame):
    def __init__(self, parent):
        wx.Frame.__init__(self, parent, wx.ID_ANY, "ListCtrl Icon Example", size=(300, 200))
        self.panel = wx.Panel(self)
        il_icons = wx.ImageList(16, 16, initialCount=5)
        il_icons.Add(wx.ArtProvider.GetBitmap(wx.ART_DELETE, wx.ART_MENU, (1, 1)))
        il_icons.Add(wx.ArtProvider.GetBitmap(wx.ART_INFORMATION, wx.ART_MENU, (16, 16)))
        il_icons.Add(wx.ArtProvider.GetBitmap(wx.ART_ERROR, wx.ART_MENU, (16, 16)))
        il_icons.Add(wx.ArtProvider.GetBitmap(wx.ART_WARNING, wx.ART_MENU, (16, 16)))
        tmp_bmp = wx.Bitmap(r"Warning.png", wx.BITMAP_TYPE_PNG)
        tmp_bmp.SetMaskColour(wx.Colour(255,255,255))
        il_icons.Add(tmp_bmp)
        lc_list = wx.ListCtrl(self.panel, wx.ID_ANY, style=wx.LC_REPORT | wx.LC_SINGLE_SEL | wx.LC_EDIT_LABELS | wx.LC_VRULES, name='lc_list')
        lc_list.AssignImageList(il_icons, which=wx.IMAGE_LIST_SMALL)
        lc_list.InsertColumn(0, 'image', format=wx.LIST_FORMAT_LEFT, width=0)
        lc_list.InsertColumn(1, 'col01', format=wx.LIST_FORMAT_LEFT, width=64)
        lc_list.InsertColumn(2, 'col02', format=wx.LIST_FORMAT_RIGHT, width=64)
        lc_list.InsertItem(0,"", -1)
        lc_list.SetItem(0, 1, 'item01')
        lc_list.SetItem(0, 2, '100', 2)
        lc_list.InsertItem(1,"", -1)
        lc_list.SetItem(1, 1, 'item02')
        lc_list.SetItem(1, 2, '200', 3)
        lc_list.SetItemBackgroundColour(1, "green")
        lc_list.InsertItem(2,"", -1)
        lc_list.SetItem(2, 1, 'item01')
        lc_list.SetItem(2, 2, '300', 5)
        lc_list.SetItemBackgroundColour(2, "yellow")
        lc_list.InsertItem(3, "", -1)
        lc_list.SetItem(3, 1, 'item06')
        lc_list.SetItem(3, 2, '300', 4)
        lc_list.SetItemBackgroundColour(3, "red")
        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(lc_list, 1, wx.EXPAND | wx.ALL)
        self.panel.SetSizer(sizer)

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

Do you get the same issue with wx.lib.agw.ultimatelistctrl? Asking out of curiosity.

Also, is there any reason why you’re setting a mask to a PNG file? It’s because the PNG as it is does not show with transparent background?

I will try UltimateListCtrl…
The “mask” is left over from my trouble shooting.
The gif has transparency & displays with transparency in an image viewer.

I read some old posts from Robin that windows only supports single bit alpha for transparency & you should use a “mask” to correct it.
I don’t know how to modify the image like this so I tried using the mask.

I’ve tried several different pngs with different masks colours (red/white etc) but none work (although I’m not confident I really understand the Wx.bitmap to know if I’m doing it correctly)…

However, the fact that the wx.artprovider images don’t work either makes me think it must be a Windows specific issue…

Seems to work fine in ULC using the demo & just adding colours to the each row…
ULC

But using the ListCtrl demo, the behaviour is the same as I see, the transparency is not applied:
LC

I guess I will just accept to lose a small bit of GUI space for the the icons to put them in the first column with the default background.

1 Like

I tested your code on linux and the icon transparency worked OK.

A very old report was raised about this issue in 2006 on the wxWidgets tracker which was then migrated to their GitHub repo:

The most recent comments are from 2012, but nothing appears to have happened since and the issue is still open.

There was another similar report opened in 2006, but it was closed as being a duplicate:

Agreed. It seems best to place ListCtrl icons in the first column only (for Windows).
By the way, TreeCtrl icon transparency works similarly to ListCtrl.

class TreeCtrl(wx.TreeCtrl):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        _blist = [
            wx.ART_FOLDER,
            wx.ART_FOLDER_OPEN,
            wx.ART_NORMAL_FILE,
        ]
        self._li = wx.ImageList(16,16)
        for icon in _blist:
            self._li.Add(wx.ArtProvider.GetBitmap(icon, wx.ART_OTHER, (16,16)))
        self.SetImageList(self._li)

        root = self.AddRoot("root", image=0)
        item = self.AppendItem(root, 'item', image=1)
        item = self.AppendItem(item, 'colourd item', image=2)
        self.SetItemBackgroundColour(item, 'yellow')

if __name__ == "__main__":
    app = wx.App()
    frm = wx.Frame(None)
    panel = TreeCtrl(frm, style=wx.TR_DEFAULT_STYLE)
    frm.Show()
    app.MainLoop()

image

But, if you change it to highlight the whole row:

    panel = TreeCtrl(frm, style=wx.TR_DEFAULT_STYLE
                               |wx.TR_FULL_ROW_HIGHLIGHT|wx.TR_NO_LINES
                               )

icons become transparent.
image

Unfortunately, ListCtrl does not have such an option.

Thanks all for your input!
For now I’ll stick with ListCtrl & icons in the first column if I get can the filthy thought of having 3 icons with different colour backgrounds out of my head…

On the positive side, I’ve discovered the wx.ArtProvider icons instead of having to find my own each time…

Experiment with UltimateListCtrl is now on my “to do” list to see how easy it would be to integrate into my existing application.