Adding an icon to a button

I’ve tried a number of things to add a resource and use an icon with a button. I’ve noticed I can access Slicer resources, but not ones in the Resources folder of my module. I’d like to do the following, hopefully with a relative path as opposed to absolute, with the icon file in the Resources/Icons directory of my module:

    loadSSFPIcon = qt.QIcon(":/Icons/SSFPicon.png")
    self.LoadSSFPButton = qt.QPushButton("Load SSFP Image Series")
    self.LoadSSFPButton.setIcon(loadSSFPIcon)
    self.layout.addWidget(self.LoadSSFPButton)

How do I accomplish this?

You can do this:

iconPath = os.path.join(os.path.dirname(self.parent.path), ‘Resources/Icons’, ‘SSFPicon.png’)
icon = qt.QIcon(iconPath)

2 posts were split to a new topic: Landmark registration for registering models

Thanks, I can see where you’re going with this, though when I tried it, self.parent.path was not recognized. What am I missing?

I think part of the problem is that I’m trying to use it from the Widget class. I’m looking at ScriptedLoadableModule.py and I see that self.parent.path works from the module class.

I’m currently trying the following, but the image still does not show in the button:

    moduleDir = os.path.dirname(slicer.util.modulePath(self.__module__))
    iconPath = os.path.join(moduleDir, 'Resources/Icons', 'SSFPicon.png')
    icon = qt.QIcon(iconPath)

Is there something else missing?
Thanks.

Did you verify that the path actually points to the image? For example you need to install the image file to the build directory as well. A working example:
https://app.assembla.com/spaces/slicerrt/subversion/source/HEAD/trunk/GelDosimetryAnalysis/src/GelDosimetryAnalysis/GelDosimetryAnalysis.py#ln2322
with the relevant CMake line
https://app.assembla.com/spaces/slicerrt/subversion/source/HEAD/trunk/GelDosimetryAnalysis/src/GelDosimetryAnalysis/CMakeLists.txt#ln19

I’ve checked the value of iconPath, and it points to the image. What build directory do you mean?
I’ve looked at the code you referenced, and what I have is consistent. A possible difference may be that I’m using an additional image, rather than the one that was defined when the module was created. Do I need a .qrc file, or something else to add new files?

I said all I know. Please try to work with this example and see what is in it that is not present in your module. One of those differences will be what causes your image not to show up. The qrc file is a good starting point.

Ok. Thanks for trying. If you think of anything else, let me know.

There are many examples for using custom icons in widget classes. For example: https://github.com/SlicerIGT/SlicerIGT/blob/b05132759b32ae3a2d3e52e9897dd28f7a39677d/PlusRemote/PlusRemote.py#L55

Using qrc file is a bit more complicated, because you need to compile resources and for that probably you need to build Slicer and your module.

Yes, this is basically the same method. What you’ll need to make sure is that the icon file is properly deployed with your module.

Yes, there are just slight differences in how to retrieve resource directory path from various classes.

From scripted module, there is also support for handling qrc files:

This will generate a <NameOfFile>Resources python module that can be imported:

from . import ExtensionWizardResources as Resources

See here for more details

Then, the corresponding resources can be used as usual:

1 Like

Thanks very much everyone. I currently have it working with this in the CMakeLists.txt:

set(MODULE_PYTHON_RESOURCES
  Resources/Icons/${MODULE_NAME}.png
  Resources/Icons/SSFPIcon.png
  )

And this in my module Widget class:

    moduleDir = os.path.dirname(slicer.util.modulePath(self.__module__))
    SSFPIconPath = os.path.join(moduleDir, 'Resources/Icons', 'SSFPIcon.png')
    loadSSFPIcon = qt.QIcon(SSFPIconPath)
    self.LoadSSFPButton = qt.QPushButton(" Load SSFP Image Series")
    self.LoadSSFPButton.setIcon(loadSSFPIcon)
    self.layout.addWidget(self.LoadSSFPButton)
1 Like

Thanks, Jean Christophe. I tried to follow this, but ran in to difficulty. Possibly with the qrc file prefix, or location. Since I was able to get it working the other way, I’ll carry on with it for now.
Thanks again.

The complexity with using qrc files is that you need to compile resources into a qrc file. That requires building of Slicer (or manual compilation).

@jcfr I tried handling qrc in my own project, but I am failing when bulding the project.

Out of curiosity I copied the ExtensionWizard to my local project and added that subdirectory to my CMakeLists.txt.

christian@christians-mbp ~/D/S4R> gcc --version
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 9.0.0 (clang-900.0.39.2)
Target: x86_64-apple-darwin17.4.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin

The output that I am getting looks as follows:

[  5%] Built target ConfigureAdditionalLauncherSettings
[ 11%] Copying python Script: ExtensionWizard.py
[ 16%] Copying python Script: ExtensionWizardLib/__init__.py
[ 22%] Copying python Script: ExtensionWizardLib/CreateComponentDialog.py
[ 27%] Copying python Script: ExtensionWizardLib/DirectoryListWidget.py
[ 33%] Copying python Script: ExtensionWizardLib/EditableTreeWidget.py
[ 38%] Copying python Script: ExtensionWizardLib/EditExtensionMetadataDialog.py
[ 44%] Copying python Script: ExtensionWizardLib/LoadModulesDialog.py
[ 50%] Copying python Script: ExtensionWizardLib/ModuleInfo.py
[ 55%] Copying python Script: ExtensionWizardLib/SettingsPanel.py
[ 61%] Copying python Script: ExtensionWizardLib/TemplatePathUtilities.py
make[2]: *** No rule to make target `/Utilities/Scripts/qrcc.py', needed by `ExtensionWizard/ExtensionWizardLib/ExtensionWizardResources.py'.  Stop.
make[1]: *** [ExtensionWizard/CMakeFiles/CopyExtensionWizardPythonScriptFiles.dir/all] Error 2
make: *** [all] Error 2

with running make -d https://gist.github.com/che85/1bff5a003b53e477a7ef403c7c3f7991

By any chance, do you have an idea what why that doesn’t work locally?

Thanks
Christian