Port of 3d slicer to qt
This presentation is the property of its rightful owner.
Sponsored Links
1 / 32

Port of 3D Slicer to Qt PowerPoint PPT Presentation


  • 129 Views
  • Uploaded on
  • Presentation posted in: General

Port of 3D Slicer to Qt. Julien Finet & Jean-Christophe Fillion -Robin Kitware Inc. June 22 th 2010. Background. Slicer version 3.x use KWWidgets VTK-style interface to Tk 3D Slicer 1.x, 2.x used Tk directly Qt

Download Presentation

Port of 3D Slicer to Qt

An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -

Presentation Transcript


Port of 3d slicer to qt

Port of 3D Slicer to Qt

Julien Finet & Jean-Christophe Fillion-Robin

Kitware Inc.

June 22th 2010


Background

Background

  • 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


Qt how to get qt

Qt – How to get Qt

  • Required version: Qt 4.6.2

  • Building Slicer with Qt

    • Use Superbuild

    • http://www.slicer.org/slicerWiki/index.php/Slicer4:Build_Instructions


Events with kwwidgets

Events with KWWidgets

  • Connect

    vtkCallbackCommand

    vtkObject::AddObserver

  • Fire event

    vtkObject::InvokeEvent()

  • Process

    myClass::myMethod()


Events with kwwidgets1

Events with KWWidgets

Object2 Callback

Node Selected Event

Object 1

Object 2


Events with kwwidgets 1 connect

Events with KWWidgets 1) Connect

this->CallbackCommand = vtkCallbackCommand::New();

this->CallbackCommand->SetClientData(object2);

this->CallbackCommand->SetCallback(vtkObject2::MethodX);

Object2 Callback

Node Selected Event

Object 1

Object 2

MethodX


Events with kwwidgets 1 connect1

Events with KWWidgets 1) Connect

object1>AddObserver(vtkObject1::NodeSelectedEvent,

this>CallbackCommand);

Object2 Callback

Node Selected Event

Object 1

Object 2


Events with kwwidgets 2 signal

Events with KWWidgets 2) Signal

void vtkObject1::Method2(){

this->InvokeEvent(vtkObject1::NodeSelectedEvent, NULL);

}

Object2 Callback

Node Selected Event

Object 1

Object 2

Method2


Events with kwwidgets 3 process

Events with KWWidgets 3) Process

void vtkObject2::MethodX(vtkObject *caller, unsigned long event, void *callData )

{

if (vtkObject2::SafeDownCast(caller) && event == vtkObject2::NodeSelectedEvent)

{

Object2 Callback

Node Selected Event

Object 1

Object 2

MethodX


Events with qt

Events with Qt

  • Connect

    QObject::connect(obj1,signal, obj2, slot);

  • Fire event

    emit mySignal();

  • Process

    myClass::mySlot();


Events with qt1

Events with Qt

Node Selected Signal

Object 1

Object 2


Events with qt 1 connect

Events with Qt 1) Connect

this->QObject::connect(obj1, SIGNAL(nodeSelected(vtkMRMLNode*)),

obj2, SLOT(methodX(vtkMRMLNode*)));

Node Selected Signal

Object 1

Object 2


Events with qt 2 signal

Events with Qt 2) Signal

void vtkObject1::Method2(){

emit this->currentNodeSelected(node);

}

Node Selected Signal

Object 1

Object 2


Events with qt 3 process

Events with Qt 3) Process

void vtkObject2::MethodX(vtkMRMLNode* node)

{

}

Node Selected Signal

Object 1

Object 2

MethodX


Qt and vtk qvtkconnect

Qt and VTK: qVTKConnect

  • qvtkConnect(vtkObject* vtk_obj, unsigned long vtk_event,const QObject* qt_obj, const char* qt_slot, float priority = 0.0)

  • Also: qvtkReconnect, qvtkDisconnect, qvtkDisconnectAll…


Qt and vtk qvtkconnect1

Qt and VTK: qVTKConnect

QVTK_OBJECT adds

the function qvtkConnect()

Usage

// CTK includes

#include <ctkVTKObject.h>

class MyWidget: public QWidget

{

Q_OBJECT

QVTK_OBJECT

public:

void setNode(vtkMRMLNode* mrmlNode);

protected slots:

void onMRMLNodeModified(vtkObject* sender);

};

void MyWidget

::setNode(vtkMRMLNode* mrmlNode)

{

qvtkConnect(

mrmlNode,

vtkCommand::ModifiedEvent,

this,

SLOT(onMRMLNodeModified(vtkObject*)));

}

void MyWidget

::onMRMLNodeModified(vtkObject* sender)

{

vtkMRMLNode* node =

vtkMRMLNode::SafeDowncast(sender);

}


Interaction between mrml qt

Interaction between MRML & Qt

valueChanged(double)

Modified Event

Qt Slider

MRML Node

Module Widget

void onNodeModified( vtkMRMLNode* node)

{

slider->setValue(node->GetValue());

}

void onValueChanged(double newValue)

{

node->SetValue(newValue);

}


Private implementation

Private Implementation

  • Hide the implementation details of an interface

  • http://en.wikipedia.org/wiki/Opaque_pointer

#include "qCTKPimpl.h"

class MyButtonPrivate;

class MyButton : public QAbstractButton

{

Q_OBJECT

public:

private:

CTK_DECLARE_PRIVATE(MyButton);

};

Don’t forget to declare the private class

friend class MyButtonPrivate; ctkPrivateInterface<MyButton, MyButtonPrivate> ctk_d;


Private implementation1

Private Implementation

class MyButtonPrivate : public qCTKPrivate<MyButton>

{

public:

CTK_DECLARE_PUBLIC(MyButton);

void init();

bool Collapsed;

};

void MyButtonPrivate::init()

{

CTK_P(MyButton);

p->setCheckable(true);

this->Collapsed = false;

}

MyButton::MyButton(QWidget* parent)

:QAbstractButton(parent)

{

CTK_INIT_PRIVATE(MyButton);

ctk_d()->init();

}

void MyButton::collapse(bool c)

{

CTK_D(MyButton);

if (c == d->Collapsed)

{

return;

}

}

MyButton* p = ctk_p()

MyButtonPrivate* d = ctk_d()


Slicer3 vs slicerqt

Slicer3 vsSlicerQt

  • SlicerQtQt only

  • Slicer3 KWWidgets + Qt


Slicer architecture

Slicer Architecture

Slicer

Base/Logic

MRML

CTK

Core

QtCore

Base/QTCore

Base/QTGUI

qMRMLWidgets

CTK

Widgets

QtGUI


Modules

Modules

  • Core Modules: Slicer3/Base/QTCoreModules

    • Transforms qSlicerTransformsModule

  • Loadable Modules: Slicer3/QTModules

    • TractographyFiducialSeedinglibqSlicerTractographyFiducialSeedingModule.so

    • Volumes libqSlicerVolumesModule.so

  • CLI Modules: Slicer3/Applications/CLI


Qtcli

QTCLI

  • Same idea than KWWidgets

    • Parse XML to build UI

  • Support

    • Shared Libraries

    • Executables

    • Python

UI panel in Slicer


Qtcli example

3) Dynamically created panel

QTCLI: Example

1) Xml description

<parameters>

<label>Registration Parameters</label>

<description>Parameters used for registration</description>

<integer>

<name>HistogramBins</name>

<flag>b</flag>

<longflag>histogrambins</longflag>

<description>Number of histogram bins to use for Mattes Mutual Information. </description>

<label>Histogram Bins</label>

<default>30</default>

<constraints>

<minimum>1</minimum>

<maximum>500</maximum>

<step>5</step>

</constraints>

</integer>

If (paramType == “integer”)

{

QSlider* intParameter = new QSlider(registrationParameters);

intParameter->setMinimum(paramMin);

intParameter->setMaximum(paramMax);

intParameter->setStep(paramStep);

intParameter->setValue(paramValue);

QObject::connect(intParameter, SIGNAL(valueChanged(int)), this, SIGNAL(onParamValueChanged(int)));

}

else if (paramType == “double”)

2) Parse parameters and generate UI


Plugin mechanism

Plugin Mechanism

  • Previously: itksys::DynamicLoader(dlopen)

  • Now: Use the QT Plugins framework

class Q_SLICER_QTMODULES_VOLUMES_EXPORT qSlicerVolumesModule :

public qSlicerAbstractLoadableModule

{

Q_INTERFACES(qSlicerAbstractLoadableModule);

public:

};

Plugin header

Q_EXPORT_PLUGIN2(qSlicerVolumesModule, qSlicerVolumesModule);

Plugin implementation

QPluginLoader loader;

loader.setFileName(pluginPath);

loader.load();

QObject * object = this->Loader.instance();

qSlicerAbstractLoadableModule* module = qobject_cast<qSlicerAbstractLoadableModule*>(object);

Plugin Loader


Loadable modules logic ui

Loadable Modules: Logic + UI

Module Plugin

(qSlicerAbstractModule)

create()

create()

Module Widget

(qSlicerAbstractModuleWidget)

Logic

(vtkSlicerModuleLogic)

Module Designer UI

qSlicer…ModuleWidget.ui

vtkMRMLScene


Widgets awareness

Widgets Awareness


Ctk widgets commontk org

CTK Widgets commontk.org

  • http://www.commontk.org/index.php/Documentation/ImageGallery

ctkFixedTitleComboBox

ctkCollapsibleGroupBox

ctkCollapsibleButton

ctkTreeComboBox

ctkColorPickerButton


Qmrmlwidgets

qMRMLWidgets

  • http://wiki.slicer.org/slicerWiki/index.php/Slicer3:Developers:Projects:QtSlicer/Gallery

  • Usually contains the slot setMRMLScene(vtkMRMLScene*)

qMRMLNodeSelector

qMRMLListWidget

qMRMLWindowLevelWidget

qMRMLTreeWidget


Widgets in qt designer

Widgets in Qt Designer

  • A plugin must be created

    • Slicer3/Libs/qMRMLWidgets/Plugins/qMRMLNodeSelectorPlugin.[h|cxx]

  • More info on

    • http://wiki.slicer.org/slicerWiki/index.php/Slicer3:Developers:Projects:QtSlicer/Tutorials/WidgetWriting


Widget example

Widget Example

class QCTK_WIDGETS_EXPORT qCTKCollapsibleButton :

public QAbstractButton

{

Q_OBJECT

Q_PROPERTY(bool collapsed READ collapsed WRITE setCollapsed)

Q_PROPERTY(intcollapsedHeight READ collapsedHeight

WRITE setCollapsedHeight)

public:

void setCollapsed(bool);

bool collapsed()const;

void setCollapsedHeight(int);

intcollapsedHeight()const;

Qt Designer

qCTKCollapsibleButton.h

10 = default value

void qCTKCollapsibleButtonPrivate::init()

{

QCTK_P(qCTKCollapsibleButton);

this->Collapsed = false;

this->CollapsedHeight = 10;

}

qCTKCollapsibleButton.cxx


Questions

Questions

  • More info: http://wiki.slicer.org/slicerWiki/index.php/Slicer3:Developers:Projects:QtSlicer


  • Login