Presentation is loading. Please wait.

Presentation is loading. Please wait.

Port of 3D Slicer to Qt Julien Finet Kitware Inc. Jan. 05 th 2010 Updated May 14 th 2010 for Slicer 3.6.

Similar presentations

Presentation on theme: "Port of 3D Slicer to Qt Julien Finet Kitware Inc. Jan. 05 th 2010 Updated May 14 th 2010 for Slicer 3.6."— Presentation transcript:

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/ /16/2011

3 Qt – How to get Qt Required version: Qt 4.6Qt 4.6 Building Slicer with Qt – 3:Developers:Projects:QtSlicer/Tutorials/Com pileWithQt 3:Developers:Projects:QtSlicer/Tutorials/Com pileWithQt Links: –Doc: –Tutorials:

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 –Volumes –… 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 3:Developers:Projects:QtSlicer/Tutorials/QtDe signer 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 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 – opers:Projects:QtSlicer/Tutorials/WidgetWriting 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 … 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 – bin/trac.cgi/wiki/WidgetPlans bin/trac.cgi/wiki/WidgetPlans

38 Questions More info: cer3:Developers:Projects:QtSlicer cer3:Developers:Projects:QtSlicer

Download ppt "Port of 3D Slicer to Qt Julien Finet Kitware Inc. Jan. 05 th 2010 Updated May 14 th 2010 for Slicer 3.6."

Similar presentations

Ads by Google