How to set an app's icon in the dock on Linux? [Solved]

I’m attempting to set the icon and title of my wxPython app on Ubuntu 22.

I’ve tried creating a .desktop file and have used wx.Frame.SetIcons(), but neither of those seem to be working. Am I missing something?

Screen Shot 2023-09-10 at 4.59.27 PM

for the OS the interpreter Python (or its launcher) is running and there should be an icon which is attached to that (and not what is interpreted) :wink:

I am using Python 3.10.12 + wxPython 4.2.1 gtk3 (phoenix) wxWidgets 3.2.2.1 on Linux Mint 21.2.

Linux Mint 21.2 is based on Ubuntu 22.04.

I am using the MATE desktop environment configured to have a single panel at the bottom of the screen which includes the quick start icons and the list of currently running windows.

In my applications I am calling the main frame’s self.SetIcon() (singular) method. This causes the icon to be displayed on the application’s title bar and on the application’s entry in the window list section of the bottom panel.

I haven’t tried the self.SetIcons() (plural) method before, so had a go in the example below and it also works for me.

import wx

class MyFrame(wx.Frame):
    def __init__(self, *args, **kwds):
        kwds["style"] = kwds.get("style", 0) | wx.DEFAULT_FRAME_STYLE
        wx.Frame.__init__(self, *args, **kwds)
        self.SetSize((400, 300))
        self.SetTitle("App Icon Test")

        # self.icon = wx.Icon("edit-find_16.png")
        # self.SetIcon(self.icon)

        icons = wx.IconBundle('edit-find_16.png')
        icons.AddIcon('edit-find_32.png')
        self.SetIcons(icons)

        self.panel = wx.Panel(self, wx.ID_ANY)
        sizer = wx.BoxSizer(wx.VERTICAL)
        self.text_ctrl = wx.TextCtrl(self.panel, wx.ID_ANY, "", style=wx.TE_MULTILINE)
        sizer.Add(self.text_ctrl, 1, wx.EXPAND, 0)
        self.panel.SetSizer(sizer)
        self.Layout()

class MyApp(wx.App):
    def OnInit(self):
        self.frame = MyFrame(None, wx.ID_ANY, "")
        self.SetTopWindow(self.frame)
        self.frame.Show()
        return True

if __name__ == "__main__":
    app = MyApp(0)
    app.MainLoop()

Here are the image files for the icons: icons.zip (3.4 KB)

The version of Mate in Linux Mint doesn’t use a dock by default.

There is a Mate dock applet that you can install, but I am reluctant to do that as I don’t know how it will affect my current setup, or if it is reversible. Even if I did install it, there is no guarantee that it would function in the same way as the dock does in your desktop environment.

In the default Mate you can add icons to the bottom panel either by using the “Add to panel” option in the Mint Main Menu, or by right-clicking on a blank space on the toolbar and selecting Add to panel... -> Custom Application Launcher.

If you use the first method the launcher will reference a desktop file in /usr/share/applications/.

If you use the second method, the launcher will reference a desktop file in ~/.local/share/applications/.

In both cases the launchers do not reference a desktop file in ~/Desktop.

I discovered this by running dconf-editor and examining the entries under org -> mate -> panel -> objects. I don’t know if there is an equivalent set of entries for your desktop.

@RichardT thanks for taking the time to put together a complete sample.

I have adapted your sample to use the self.SetIcon() (singular) method which you are more familar with. Unfortunately I still see no icon in the dock or top bar:
Screen Shot 2023-09-11 at 9.38.01 AM

Exact code I used

example.py:

import wx

class MyFrame(wx.Frame):
    def __init__(self, *args, **kwds):
        kwds["style"] = kwds.get("style", 0) | wx.DEFAULT_FRAME_STYLE
        wx.Frame.__init__(self, *args, **kwds)
        self.SetSize((400, 300))
        self.SetTitle("App Icon Test")

        self.icon = wx.Icon('appicon.png')
        self.SetIcon(self.icon)

        self.panel = wx.Panel(self, wx.ID_ANY)
        sizer = wx.BoxSizer(wx.VERTICAL)
        self.text_ctrl = wx.TextCtrl(self.panel, wx.ID_ANY, "", style=wx.TE_MULTILINE)
        sizer.Add(self.text_ctrl, 1, wx.EXPAND, 0)
        self.panel.SetSizer(sizer)
        self.Layout()

class MyApp(wx.App):
    def OnInit(self):
        self.frame = MyFrame(None, wx.ID_ANY, "")
        self.SetTopWindow(self.frame)
        self.frame.Show()
        return True

if __name__ == "__main__":
    app = MyApp(0)
    app.MainLoop()

appicon.png:
appicon

System configuration

I am using Python 3.10.12 + wxPython 4.1.1 gtk3 (phoenix) wxWidgets 3.1.5 on Ubuntu 22

Interesting. I already had an in-progress .desktop file (based on this tutorial) with the correct icon and title.

I just tried installing it to ~/.local/share/applications/. And lo I have an icon in the dock!
Screen Shot 2023-09-11 at 10.01.59 AM

So apparently a valid .desktop file installed in ~/.local/share/applications/ or /usr/share/applications/ is what is needed to define a dock icon for a wxPython app in Ubuntu, for any future readers.

1 Like

There’s one more important detail:

  • The name of the .desktop file must match the name of the executable it links to. Otherwise the icon doesn’t show up.

In my example above I have a crystal.desktop file pointing to the crystal binary installed via pipx. If I rename the desktop file to something like net.dafoster.Crystal.desktop then the generic gear icon shows up in the dock rather than the proper app icon!