Download presentation
Presentation is loading. Please wait.
Published byGrace Cooke Modified over 10 years ago
1
3D Slicer Qt Port Julien Finet Kitware Inc. Dec. 16 th 2009
2
Background 3D Slicer version 3.x use KWWidgets –VTK-style interface to Tk –3D Slicer 1.x, 2.x used Tk directly Qt 4.6 –Embedded Linux, Mac OS X, Windows, Linux/X11, Windows CE/Mobile, Symbian, Maemo –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
Qt – First steps Hello World Signals / Slots Events vs Signals/Slots Layouts What QObject does for you ? –Parent / child relationship Designer Not only GUI widgets in 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 –qSlicerTransformsModule Loadable Modules: Slicer3/QTModules –Measurements –Volumes CLI Modules
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 (qSlicerAbstractModuleLogic) create() UI (qSlicerAbstractModuleWidget) Module (qSlicerAbstractModule) vtkMRMLScene QWidget QObject
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/qSlicerMyModuleLogic.[h/cxx] (optional) –MyModule/Resources/qSlicerMyModule.qrc (optional) –MyModule/Resources/UI/qSlicerMyModule.ui
14
MyModule UI – 1 / 4 Open Qt Designer with QT_PLUGIN_PATH set to Slicer3-build/bin –Designing a module UI requires the plugins: qCTKWidgets, qVTKWidgets, qMRMLWidgets and qSlicerBaseQTGUI –Warning: plugins must be compiled under the same mode than Qt (Release vs. Debug) –On Linux: cd Slicer3-build; python Designer.py –More info on http://wiki.slicer.org/slicerWiki/index.php/Slicer3:D evelopers:Projects:QtSlicer/Tutorials/QtDesigner
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 be 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 qSlicerAbstractModuleLogic* createLogic(); }; #endif qSlicerMyModule.h
20
qSlicerMyModule.cxx #include "qSlicerMyModule.h" // SlicerQT includes #include "qSlicerMyModuleWidget.h" // QT includes #include //----------------------------------------------------------------------------- Q_EXPORT_PLUGIN2(qSlicerMyModule, qSlicerMyModule); //----------------------------------------------------------------------------- qSlicerWelcomeModule(QObject* parent) :public qSlicerAbstractLoadableModule(parent) { } //----------------------------------------------------------------------------- qSlicerAbstractModuleWidget * qSlicerWelcomeModule::createWidgetRepresentation() { return new qSlicerWelcomeModuleWidget; } //----------------------------------------------------------------------------- qSlicerAbstractModuleWidget * qSlicerTransformsModule::createWidgetRepresentation() { return new qSlicerMyModuleWidget; } //----------------------------------------------------------------------------- qSlicerAbstractModuleLogic* qSlicerTransformsModule::createLogic() { return 0; } Instantiate the UI widget qSlicerMyModule.cxx
21
qSlicerMyModuleWidget.h #ifndef __qSlicerMyModuleWidget_h #define __qSlicerMyModuleWidget_h // SlicerQT includes #include "qSlicerAbstractModuleWidget.h" // qCTK includes #include #include "qSlicerMyModuleWin32Header.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 Generated 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 name 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(); … }; struct qSlicerTransformsModuleWidgetPrivate: public qCTKPrivate, public Ui_qSlicerTransformsModule { 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
qCTKPimpl 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
qCTKPimpl //----------------------------------------------------------------------------- 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/qMRMLNo deSelectorPlugin.[h|cxx] –Slicer3/Libs/qMRMLWidgets/Plugins/qMRML NodeSelectorPlugin.[h|cxx] More info on –http://wiki.slicer.org/slicerWiki/index.php/Slicer 3:Developers:Projects:QtSlicer/Tutorials/Widg etWriting
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, qSlicerIOManager QTCLI qSlicerCLIModule QTCoreModules qSlicerCamerasModules, qSlicerTransformsModule QTCore qSlicerModuleFactory 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 ?
Similar presentations
© 2024 SlidePlayer.com Inc.
All rights reserved.