I like the idea of having a “UI” class be part of the auto-generated module code. It would encourage best practices. It would mean updating the templates.
I haven’t thought about promoting using .ui files to the general public, but I agree that it could work well.
To make Qt designer (with all custom ctk, qMRML, Slicer widgets) available without requiring users to install a compatible version of Qt, we would need to bundle Qt designer binaries in the installation package. It should be no problem, as it requires only a few extra files of a total size of 6 MB (designer.exe, Qt5Designer.dll, and Qt5DesignerComponents.dll; Qt designer plugins are already included). @jcfr what do you think?
In addition to bundling designer executable, we should add an “Edit .ui file” button to the Reload&Test section and add an ExtensionWizard template.
That seems reasonable.
And if build system not already take care of fixing up the executable … we may have to do something specific.
Wow, bundling Qt Designer with Slicer is a fascinating idea. That could be convenient for everyone, but I also imaging there’s a category of people who might contribute to the ui who wouldn’t think of doing it in C++ or Python but would like using the designer.
I suppose the logical next step would be including all of Qt Creator? We need to draw the line somewhere but this could be an optional install or developer extension.
I’ve tried to update the current scripted module template to use a .ui file to generate GUI and it worked really well. It reduced and simplified the code a lot.
Reload works nicely: to update the GUI, it is enough to save the .ui file in Qt Designer and click Reload in Slicer.
Widget variables can be automatically exposed as
self.ui.myWidget (similarly how variables are accessible in C++ by generating a skeleton file).
I’ve submitted a pull request so that you can have a look: https://github.com/Slicer/Slicer/pull/1072/files#diff-c12bcbe4f4bab89847136fc032496bd4R36
@jcfr It works so nicely that I think it would worth the time adding designer to the package. Could you have a look? If it’s very easy then it might make sense to include it in 4.10.1.
My group has been using Qt Designer for generating UI files and using them in our Slicer python code using
slicer.util.loadUI() for well over a year now. Qt Designer definitely helps with quick prototyping of GUIs and we generally prefer this unless the widget is something extremely simple. For beginners, coding QLayout policies and such is really intimidating and difficult to understand without playing around with something like Qt Designer.
I think it is also valuable to maintain the simple template that can be generated via the python script which Jean-Christophe Fillion-Robin et Steve Pieper wrote some years ago. I also think that said script should be in some bin directory associated with slicer binary as well so you don’t have to download the source to get it. It gives you a quick path to writing a “hello world” module.
We’ll maintain both scripted module templates (the current one where GUI is created by scripting, and the new one where GUI is loaded from .ui file). ExtensionWizard module can generate modules from these templates.
Following r27706, Qt designer is expected to be packages on the three platform.
On Linux and Windows, it should be started using
./Slicer --designer, on macOS, it should be directly started.
Thinking more about it, we will have to generate a dedicated launcher (similarly to what is done for Python) because we must set variables like
QT_PLUGIN_PATH also on macOS
If module UI file is found then a new button “Edit UI” appears in Reload&Test section of scripted modules. That button relies on a slicer.util function that uses Slicer --designer to launch the designer. So, it would be great if this would work on all platforms.
Currently, the button is only shown for non-installed Slicer. Now that designer is bundled with installed Slicer, too, the button should be shown for installed Slicer as well. @jcfr please make the change (I’m traveling).
Agreed. The next set of commits should enable that.
In addition of supporting
Slicer --designer where the Slicer launcher is available, the cross-platform approach to start Qt designer is to run
SlicerDesigner executable found in the
It was needed to configure a launcher because on macOS it is not possible to run
./Slicer --designer from an install tree.
Based on tomorrow nightly build, we may have to tweak the packaging of designer on Windows and macOS. After this is tested, we will initiate the 4.10.1 release process.
Just an FYI to all, I have recently stumbled upon this issue.
I will work on a fix, but until then, the
slicer.util.loadUI() approach can’t load re-usable widgets from extensions.
Looking at someone else’s code and noticed that they use ScriptedLoadableModuleWidget.setup(self). If one starts from the python generated module template this function is not called and the template instead has code to produce a reload button reload and test button and connections and a method to reload modules.
The older templates included the developer section, but now they use the superclass:
Is that not working?
I ran the script more than a year ago. Could be my fault. Will check.
Yep I was using a template I generated too long ago…
I have thinking about UI reuse a bit more (as opposed to logic reuse). Do you all agree that it is just a case of putting all the UI stuff in a new class… let’s call it ModuleNameWidgetUI with some constructor expecting a layout whereby said class is also designed so that MRML node(s) can be “passed in” and for each MRML “passed in” the node selection widget is not created and the “passed in” value is used instead?
The current design is that each module offers a number of reusable widgets. The module widget is built up a couple of these widgets. This results in much simpler design and more clean interfaces than trying to make a large monolithic module widget highly configurable with lots of options.
Some module widgets may contain sections that are not available directly as reusable widgets (we did not have the extra time to do that or did not think that there would be a strong need for it). If you want to reuse such sections in your module then the solution is to factor out those parts as a separate widget - as it has been done several times in the past.