Download presentation
Presentation is loading. Please wait.
Published byDanielle Reyes Modified over 11 years ago
1
Port of 3D Slicer to Qt Julien Finet Kitware Inc. Jan. 05 th 2010 Updated May 14 th 2010 for Slicer 3.6
2
Background 3D Slicer version 3.x use KWWidgets –VTK-style interface to Tk –3D Slicer 1.x, 2.x used Tk directly Qt –Embedded Linux, Mac OS X, Windows, Linux/X11, Windows CE/Mobile, Symbian, Maemo –Commercial/LGPL –600+ classes –Tens of thousands of applications –15+ millions of users NIH Supplement to help with port –9/17/2009 - 9/16/2011
3
Qt – How to get Qt Required version: Qt 4.6Qt 4.6 Building Slicer with Qt –http://wiki.slicer.org/slicerWiki/index.php/Slicer 3:Developers:Projects:QtSlicer/Tutorials/Com pileWithQthttp://wiki.slicer.org/slicerWiki/index.php/Slicer 3:Developers:Projects:QtSlicer/Tutorials/Com pileWithQt Links: –Doc: http://qt.nokia.com/doc/4.6/index.htmlhttp://qt.nokia.com/doc/4.6/index.html –Tutorials: http://qt.nokia.com/doc/4.6/tutorials.html http://qt.nokia.com/doc/4.6/tutorials.html
4
First steps with Qt
5
Qt in Slicer Events with KWWidgets 1.Fire event 2.Connect 3.Process void vtkSlicerCamerasGUI::AddGUIObservers() { … this->ViewSelectorWidget->AddObserver( vtkSlicerNodeSelectorWidget::NodeSelectedEvent, (vtkCommand *)this->GUICallbackCommand ); … } void vtkSlicerCamerasGUI::ProcessGUIEvents( vtkObject *caller, unsigned long event, void *callData ) { if (vtkSlicerNodeSelectorWidget::SafeDownCast(caller)) { if (event == vtkSlicerNodeSelectorWidget::NodeSelectedEvent) { … } void vtkSlicerNodeSelectorWidget::ProcessCommand(char *selectedID) { … this->InvokeEvent(vtkSlicerNodeSelectorWidget::NodeSelectedEvent, NULL); … } vtkSlicerNodeSelectorWidget.cxx vtkSlicerCamerasGUI.cxx
6
Qt in Slicer Events with Qt 1.Fire event 2.Connect 3.Process void qSlicerCamerasModuleWidget::setup() { … connect(d->ViewNodeSelector, SIGNAL(currentNodeChanged(vtkMRMLNode*)), this, SLOT(onCurrentViewNodeChanged(vtkMRMLNode*))); … } void qSlicerCamerasModuleWidget::onCurrentViewNodeChanged(vtkMRMLNode* mrmlNode) { vtkMRMLViewNode* currentViewNode = vtkMRMLViewNode::SafeDownCast(mrmlNode); … } void qMRMLNodeSelector::nodeIdSelected(int index) { … emit currentNodeChanged(d->MRMLCurrentNode); } qSlicerCamerasModuleWidget.cxx qMRMLNodeSelector.cxx
7
Qt and VTK qVTKConnect() –Based on VTK/GUISupport/Qt/vtkEventQtSlotConnect void qMRMLNodeSelector::addNode(vtkMRMLNode* mrmlNode) { … this->qvtkConnect(mrmlNode, vtkCommand::ModifiedEvent, this, SLOT(onMRMLNodeModified(vtkObject*, void*))); … } // qVTK includes #include … class QMRML_WIDGETS_EXPORT qMRMLNodeSelector : public qCTKAddRemoveComboBox { Q_OBJECT QVTK_OBJECT public: … qMRMLNodeSelector.h qMRMLNodeSelector.cxx QVTK_OBJECT adds the function qvtkConnect()
8
Porting Slicer to Qt Create Qt/KWW co-existence layer (done!) Prototype a few modules (done!) Create an architecture for Qt based modules (in process) Train developers (first session at January 2010 Project Week) Port modules (ongoing through 2010…) Turn off KWW (by end of 2010?) Continual Improvement (through end of supplement and beyond…)
9
Porting Slicer to Qt Slicer: Qt only Slicer: KWWidgets + Qt Executable: Slicer3 Executable: SlicerQT
10
Modules Core Modules: Slicer3/Base/QTCoreModules –Transforms qSlicerTransformsModule –… Loadable Modules: Slicer3/QTModules –TractographyFiducialSeeding libqSlicerTractographyFiducialSeedingModule.so –Volumes libqSlicerVolumesModule.so –… CLI Modules: Slicer3/Applications/CLI –…
11
Plugin Mechanism Previously: itksys::DynamicLoader(dlopen) Now: Use the QT Plugins frameworkQT Plugins … class Q_SLICER_QTMODULES_VOLUMES_EXPORT qSlicerVolumesModule : public qSlicerAbstractLoadableModule { Q_INTERFACES(qSlicerAbstractLoadableModule); public: … }; … Q_EXPORT_PLUGIN2(qSlicerVolumesModule, qSlicerVolumesModule); … QPluginLoader loader; loader.setFileName(pluginPath); loader.load(); QObject * object = this->Loader.instance(); qSlicerAbstractLoadableModule* module = qobject_cast (object); Plugin Loader Plugin implementation Plugin header
12
Modules: Logic + UI Logic (vtkSlicerModuleLogic) create() UI (qSlicerAbstractModuleWidget) Module (qSlicerAbstractModule) vtkMRMLScene QWidget QObject qSlicer…ModuleWidget.ui Designer UI file
13
How to write a loadable module Create directories in Slicer3/QTModules –MyModule –MyModule/Resources –MyModule/Resources/UI –MyModule/Resources/Icons (optional) Create the files –MyModule/CMakeLists.txt –MyModule/qSlicerMyModule.[h/cxx] –MyModule/qSlicerMyModuleWidget.[h/cxx] –MyModule/Logic/vtkSlicerMyModuleLogic.[h/cxx] (optional) Can also reuse the module logic in Modules/MyModule/Logic –MyModule/Resources/qSlicerMyModule.qrc (optional) –MyModule/Resources/UI/qSlicerMyModule.ui
14
MyModule UI – 1 / 4 Open Qt designer –cd Slicer3-build; Slicer3.exe --designer –Warning: on Windows, plugins must be compiled under the same mode than Qt (Release/Debug) –More info on http://wiki.slicer.org/slicerWiki/index.php/Slicer 3:Developers:Projects:QtSlicer/Tutorials/QtDe signer http://wiki.slicer.org/slicerWiki/index.php/Slicer 3:Developers:Projects:QtSlicer/Tutorials/QtDe signer
15
My Module UI – 2 / 4 Create a UI form: –MyModule/Resources/UI/qSlicerMyModule.ui qSlicerWidget has the signal mrmlSceneChanged() Qt Designer
16
MyModule UI – 3 / 4 Drag widgets on the form Names are importantQt Designer
17
My Module UI – 4 / 4 Connect widgets together with the signals/slots Here the MRMLScene of the module is propagated to the NodeSelector Qt Designer
18
MyModule Resources If icons are used, they should go in –MyModule/Resources/Icons/ Update the resource.qrc file –MyModule/Resources/qSlicerMyModule.qrc Icons/MyIcon.png … qSlicerMyModule.qrc
19
qSlicerMyModule.h #ifndef __qSlicerMyModule_h #define __qSlicerMyModule_h // SlicerQT includes #include "qSlicerAbstractLoadableModule.h #include "qSlicerMyModuleWin32Header.h // generated by CMake class qSlicerMyModulePrivate; class Q_SLICER_QTMODULES_MYMODULE_EXPORT qSlicerMyModule : public qSlicerAbstractLoadableModule { Q_OBJECT public: qSlicerTransformsModule(QObject *parent=0); virtual QString title()const { return Transforms; } virtual QString helpText()const; virtual QString acknowledgementText()const; protected: // Create and return a widget representation of the object virtual qSlicerAbstractModuleWidget * createWidgetRepresentation(); virtual vtkSlicerModuleLogic* createLogic(); }; #endif qSlicerMyModule.h
20
qSlicerMyModule.cxx #include "qSlicerMyModule.h" // SlicerQT includes #include "qSlicerMyModuleWidget.h" // QT includes #include //----------------------------------------------------------------------------- Q_EXPORT_PLUGIN2(qSlicerMyModule, qSlicerMyModule); //----------------------------------------------------------------------------- qSlicerMyModule(QObject* parent) :public qSlicerAbstractLoadableModule(parent) { } //----------------------------------------------------------------------------- qSlicerAbstractModuleWidget * qSlicerTransformsModule::createWidgetRepresentation() { return new qSlicerMyModuleWidget; } //----------------------------------------------------------------------------- vtkSlicerModuleLogic* qSlicerTransformsModule::createLogic() { return 0; } Instantiate the UI widget qSlicerMyModule.cxx Dont forget to export the module
21
qSlicerMyModuleWidget.h #ifndef __qSlicerMyModuleWidget_h #define __qSlicerMyModuleWidget_h // SlicerQT includes #include "qSlicerAbstractModuleWidget.h" // qCTK includes #include #include "qSlicerMyModuleExport.h" class qSlicerMyModuleWidgetPrivate; class Q_SLICER_QTMODULES_MYMODULE_EXPORT qSlicerMyModuleWidget : public qSlicerAbstractModuleWidget { Q_OBJECT public: typedef qSlicerAbstractModuleWidget Superclass; qSlicerMyModuleWidget(QWidget *parent=0); protected: virtual void setup(); private: QCTK_DECLARE_PRIVATE(qSlicerMyModuleWidget); }; #endif Configured by CMake Setup the UI qSlicerMyModuleWidget.h
22
qSlicerMyModuleWidget.cxx #include "qSlicerMyModuleWidget.h" #include "ui_qSlicerMyModule.h" //----------------------------------------------------------------------------- struct qSlicerMyModuleWidgetPrivate: public qCTKPrivate, public Ui_qSlicerMyModule { }; //----------------------------------------------------------------------------- qSlicerMyModuleWidget ::qSlicerMyModuleWidget( QWidget* parent) :qSlicerAbstractModuleWidget(parent) { QCTK_INIT_PRIVATE(qSlicerMyModuleWidget); } //----------------------------------------------------------------------------- void qSlicerWelcomeModuleWidget::setup() { QCTK_D(qSlicerWelcomeModuleWidget); d->setupUi(this); } Generated by CMake (via uic) from qSlicerMyModule.ui Creates the QWidgets … void setupUi(qSlicerWidget *qSlicerMyModule) { … verticalLayout = new QVBoxLayout(qSlicerMyModule); CTKCollapsibleButton = new qCTKCollapsibleButton(qSlicerMyModule); CTKCollapsibleButton->setCollapsed(true); horizontalLayout = new QHBoxLayout(CTKCollapsibleButton); label = new QLabel(CTKCollapsibleButton); horizontalLayout->addWidget(label); horizontalSlider = new QSlider(CTKCollapsibleButton); … } Ui_qSlicerMyModule.h qSlicerMyModuleWidget.cxx
23
MyModule project Create a CMakeLists.txt in MyModule Add your module in QTModules/CMakeLists.txt SET(qt_module_SRCS qSlicerMyModule.cxx qSlicerMyModule.h qSlicerMyModuleWidget.cxx qSlicerMyModuleWidget.h ) Slicer3_build_qtmodule( NAME MyModule TITLE My Module EXPORT_DIRECTIVE "Q_SLICER_QTMODULES_MYMODULE_EXPORT SRCS ${qt_module_SRCS} MOC_SRCS qSlicerMyModuleWidget.h UI_SRCS Resources/UI/qSlicerMyModule.ui TARGET_LIBRARIES ${qt_module_target_libraries} RESOURCES Resources/qSlicerMyModule.qrc ) QTModules/MyModule/CMakeLists.txt
24
Tadam ! MyModule Panel here MyModule Slicer3
25
Module: with a logic and slots: qSlicerTransformsModuleWidget class … qSlicerTransformsModuleWidget : public qSlicerAbstractModuleWidget { Q_OBJECT … public slots: void loadTransform(); … }; class qSlicerTransformsModuleWidgetPrivate: public qCTKPrivate, public Ui_qSlicerTransformsModule { public: qSlicerTransformsModuleLogic* logic() const; }; void qSlicerTransformsModuleWidget::loadTransform() { QCTK_D(qSlicerTransformsModuleWidget); QString fileName = QFileDialog::getOpenFileName(this); d->logic()->AddTransform(fileName); } void qSlicerTransformsModuleWidget::setup() { QCTK_D(qSlicerTransformsModuleWidget); d->setupUi(this); … this->connect(d->LoadTransformPushButton, SIGNAL(clicked()), SLOT(loadTransform())); } Called by the Load Transform pushbutton
26
Widgets LibraryQTVTKMRML qCTKWidgetsYes qVTKWidgetsYes qMRMLWidgetsYes qSlicerBaseQTGUIYes
27
qCTKWidgets Common Toolkit (CTK) Currently hosted on the Slicer repository qCTKCollapsibleButton qCTKCollapsibleGroupBox qCTKColorPickerButton qCTKTreeComboBox qCTKFixedTitleComboBox
28
qMRMLWidgets Depends on QT and MRML Usually contains the slot setMRMLScene(vtkMRMLScene*) qMRMLNodeSelector qMRMLMatrixWidget qMRMLTreeWidget qMRMLListWidget
29
Private Implementation Hide the implementation details of an interface http://en.wikipedia.org/wiki/Opaque_pointe r // qCTK includes #include "qCTKPimpl.h" // QT includes #include class qCTKCollapsibleButtonPrivate; class QCTK_WIDGETS_EXPORT qCTKCollapsibleButton : public QAbstractButton { Q_OBJECT public: qCTKCollapsibleButton(QWidget *parent = 0); … private: QCTK_DECLARE_PRIVATE(qCTKCollapsibleButton); }; #endif friend class qCTKCollapsibleButtonPrivate; qCTKPrivateInterface qctk_d; Dont forget to declare the private class
30
Private Implementation //----------------------------------------------------------------------------- class qCTKCollapsibleButtonPrivate : public qCTKPrivate { public: QCTK_DECLARE_PUBLIC(qCTKCollapsibleButton); void init(); bool Collapsed; … }; //----------------------------------------------------------------------------- void qCTKCollapsibleButtonPrivate::init() { QCTK_P(qCTKCollapsibleButton); p->setCheckable(true); // checked and Collapsed are synchronized: checked != Collapsed p->setChecked(true); this->Collapsed = false; } //----------------------------------------------------------------------------- qCTKCollapsibleButton::qCTKCollapsibleButton(QWidget* parent) :QAbstractButton(parent) { QCTK_INIT_PRIVATE(qCTKCollapsibleButton); qctk_d()->init(); } //----------------------------------------------------------------------------- void qCTKCollapsibleButton::collapse(bool c) { QCTK_D(qCTKCollapsibleButton); if (c == d->Collapsed) { return; } … } friend class qCTKCollapsibleButton qctk_d.setPublic(this) qCTKCollapsibleButtonPrivate* d = qctk_d() qCTKCollapsibleButton* p = qctk_p()
31
Widgets in Qt Designer A plugin must be created –Slicer3/Libs/qCTKWidgets/Plugins/qMRMLNodeSelec torPlugin. [ h|cxx ] –Slicer3/Libs/qMRMLWidgets/Plugins/qMRMLNodeSel ectorPlugin. [ h|cxx ] More info on –http://wiki.slicer.org/slicerWiki/index.php/Slicer3:Devel opers:Projects:QtSlicer/Tutorials/WidgetWritinghttp://wiki.slicer.org/slicerWiki/index.php/Slicer3:Devel opers:Projects:QtSlicer/Tutorials/WidgetWriting
32
Widget Example Qt Designer class QCTK_WIDGETS_EXPORT qCTKCollapsibleButton : public QAbstractButton { Q_OBJECT Q_PROPERTY(bool collapsed READ collapsed WRITE setCollapsed) Q_PROPERTY(int collapsedHeight READ collapsedHeight WRITE setCollapsedHeight) … public: void setCollapsed(bool); bool collapsed()const; void setCollapsedHeight(int); int collapsedHeight()const; qCTKCollapsibleButton.h void qCTKCollapsibleButtonPrivate::init() { QCTK_P(qCTKCollapsibleButton); … this->Collapsed = false; … this->CollapsedHeight = 10; … } qCTKCollapsibleButton.cxx 10 = default value
33
QTCLI Same idea than KWWidgets –Parse XML to build UI Support –Shared Libraries –Executables –Python UI panel in Slicer
34
QTCLI: Example … Registration Parameters Parameters used for registration HistogramBins b histogrambins Number of histogram bins to use for Mattes Mutual Information. Histogram Bins 30 1 500 5 … qCTKCollapsibleButton* registrationParameters = new qCTKCollapsibleButton(Registration Parameters, this); QLabel* histogramBinLabel = new QLabel(Histogram Bins, registrationParameters); QSlider* histogramBin = new QSlider(registrationParameters); histogramBin->setMinimum(1); histogramBin->setMaximum(500); histogramBin->setStep(5); histogramBin->setValue(30); QObject::connect(histogramBin, SIGNAL(valueChanged(int)), this, SIGNAL(onHistogramValueChanged(int))); … UI panel in Slicer Xml description Generated code
35
Slicer Architecture QTBase qSlicerAbstractModule QTCLI qSlicerCLIModule QTCoreModules qSlicerCamerasModules, qSlicerTransformsModule QTCore qSlicerModuleFactory,, qSlicerCoreIOManager QTGUI qSlicerModulePanel, qSlicerApplication, qSlicerIOManager
36
Whats coming soon ? CLI modules Node tree widgets 3D view widget Lookup table editor Slice view widget …
37
Whats in the Pipeline ? Wizards Python More widgets –help from the CTK community –http://www.commontk.org/cgi- bin/trac.cgi/wiki/WidgetPlanshttp://www.commontk.org/cgi- bin/trac.cgi/wiki/WidgetPlans
38
Questions More info: http://wiki.slicer.org/slicerWiki/index.php/Sli cer3:Developers:Projects:QtSlicer http://wiki.slicer.org/slicerWiki/index.php/Sli cer3:Developers:Projects:QtSlicer
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.