Maverick/Creating your first application

From KitwarePublic
< Maverick
Revision as of 02:06, 15 September 2009 by Aylward (talk | contribs) (New page: This page describes how to create an application from scratch using Maverick. Look at the applications directory. = Starting the project = A basic Maverick application is composed of 5 f...)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigationJump to search

This page describes how to create an application from scratch using Maverick. Look at the applications directory.

Starting the project

A basic Maverick application is composed of 5 files:

  1. CMakeLists.txt: configuration file for CMake
  2. main.cxx: which starts the application
  3. MyApplicationUI.ui: Qt Designer file (should not be edited by hand)
  4. MyApplicationUI.h: derived class from the Qt MyApplicationUI application class
  5. MyApplicationUI.cxx: derived class from the Qt MyApplicationUI application class

Creating CMakeLists.txt

Nothing really new here.

 PROJECT(MyApplication)

 # Find QT
 FIND_PACKAGE(Qt4 REQUIRED)
 IF(UNIX)
 IF(QT4_FOUND)
   INCLUDE(${QT_USE_FILE})
 ENDIF(QT4_FOUND)
 ENDIF(UNIX)

 INCLUDE_DIRECTORIES(
   ${QT_INCLUDE_DIR}
   ${QT_QTGUI_INCLUDE_DIR}
   ${QT_QTCORE_INCLUDE_DIR}
   ${CMAKE_CURRENT_BINARY_DIR}
   ${CMAKE_CURRENT_SOURCE_DIR}
   )

 LINK_LIBRARIES (${QT_LIBRARIES})

 SET(MyApplication_SRCS
   main.cxx
   MyApplicationUI.h
   MyApplicationUI.cxx
 )

 SET(MyApplication_MOC_SRCS MyApplicationUI.h)
 SET(MyApplication_UI_SRCS MyApplicationUI.ui)

 QT4_WRAP_CPP(MyApplication_SRCS ${MyApplication_MOC_SRCS})
 QT4_WRAP_UI(MyApplication_UI_CXX ${MyApplication_UI_SRCS})

 ADD_EXECUTABLE(MyApplication ${MyApplication_SRCS} ${MyApplication_UI_CXX})

 # Order of the library is important!
 TARGET_LINK_LIBRARIES(MyApplication
   QmModuleGUI
   MaverickModule
   QmWidgets 
   ModuleDescriptionParser
   )

Creating main.cxx

The main.cxx launch the Dialog window and should look like this:

 #include <qapplication.h>
 #include "MyApplicationUI.h"

 int main(int argc, char **argv)
   {
   QApplication app(argc, argv);
   MyApplicationUI dialog;
   dialog.show();
   return app.exec();
   }

Creating the MyApplicationUI class

Header file (MyApplicationUI.h)

 class MyApplicationUI : public QMainWindow, private Ui::Dialog
 {
 Q_OBJECT
  
 public:
   MyApplicationUI(QWidget *parent = 0);
   ~MyApplicationUI();

 public slots:

   void CheckTimeouts();

 private:

   mav::Scene*                m_Scene; 
   QTimer*                    m_Timer;
   vtkSlicerApplicationLogic* m_ApplicationLogic;
 };

Implementation file (MyApplicationUI.cxx)

 #include <QtGui> 
 #include "MyApplicationUI.h"
 #include "vtkPulseGenerator.h"

 MyApplicationUI::MyApplicationUI(QWidget *parent)
 {
   setupUi(this); // this sets up GUI
  
   // Create the scene
   m_Scene = sceneWidget->GetScene();

   // Setup the timer
   m_Timer = new QTimer(this);
   m_Timer->setInterval(100); //ms
   connect(m_Timer, SIGNAL(timeout()), this,SLOT( CheckTimeouts()));
   m_Timer->start();

   m_ApplicationLogic = vtkSlicerApplicationLogic::New();
   m_ApplicationLogic->SetMRMLScene( m_Scene->GetMRMLScene() );
   m_ApplicationLogic->ProcessMRMLEvents (m_Scene->GetMRMLScene(), vtkCommand::ModifiedEvent,
                                          NULL);  
   m_ApplicationLogic->SetAndObserveMRMLScene ( m_Scene->GetMRMLScene() );
   m_ApplicationLogic->CreateProcessingThread();

   // Workflow
   workflowManager->SetPreviousButton(previousButton);
   workflowManager->SetNextButton(nextButton);
   workflowManager->SetWorkflowLabel(workflowLabel);
   workflowManager->Update();
   workflowManager->SetInitialStep(0);
   }

 /** Destructor */
 MyApplicationUI::~MyApplicationUI()
   {
   m_ApplicationLogic->Delete();
   delete m_Timer;
   }

 /** Check the timeouts */
 void MyApplicationUI::CheckTimeouts()
   {
   vtkPulseGenerator::CheckTimeouts();
   }

Creating Main UI Form with Qt Designer

  • Open QtDesigner and select File->New Form...
  • Select Dialog without Buttons
  • Save the file as MyApplicationUI.ui

Creating WorkflowManager

  • Select in the Maverick [Common Qt Widgets]: QmWorkflowManagerWidget and place the worflow manager where you want it.
  • Rename the WorkflowManagerWidget to workflowManager
  • Create a Push Button and rename it to "nextButton"
  • Create another Push Button and rename it to "previousButton"
  • Create a Label and rename it to "workflowLabel"
  • In the constructor of your derived UI class (from MyApplication.ui) insert the following lines to connect the buttons and label to the workflow manager
 workflowManager->SetPreviousButton(previousButton);
 workflowManager->SetNextButton(nextButton);
 workflowManager->SetWorkflowLabel(workflowLabel);
 workflowManager->Update();
 workflowManager->SetInitialStep(0);

Creating the Scene

  • Select in the Maverick [Common Qt Widgets]: QmSceneWidget and place it where you want. Note that it will not be shown in the GUI.
  • Rename it to sceneWidget
  • From within your code you are now able to access the mav::Scene using
 mav::Scene* myMaverickScene = sceneWidget->GetScene();

Creating the Scene Browser

The scene browser widget displays the objects in the scene and allows for selection of objects.

  • Select in the Maverick [Common Qt Widgets]: QmSceneBrowserWidget and place it where you want.
  • Rename it to sceneBrowserWidget
  • Go to Edit->Edit Signals/Slots (or press F4)
  • Connect sceneWidget::getScene() event to sceneBrowserWidget::SetScene() slot

Creating the Object Property Widget

  • Select in the Maverick [Common Qt Widgets]: QmObjectPropertyWidget and place it where you want.
  • Rename it to objectPropertyWidget
  • Go to Edit->Edit Signals/Slots (or press F4)
  • Connect sceneBrowserWidget::selectObject(mav::VisualObject*) event to objectPropertyWidget::SetObject(mav::VisualObject*) slot

Creating a Stacked Display Widget

The stacked display widget allows to stack different visualization widget. In conjunction with the QmStackedDisplayToolbarWidget, it provides a simple way of visualizing the mavScene.

  • Select in the Maverick [Common Qt Widgets]: QmStackedDisplayWidget and place it where you want.
  • Rename it to stackedDisplayWidget
  • Create a new page and add a QmVTKRenderWidget and rename it to renderWidget3D
    • Go to Edit->Edit Signals/Slots (or press F4)
    • Connect sceneWidget::getScene() event to renderWidget3D::SetScene() slot
    • Connect sceneWidget::modified() event to renderWidget3D::Update() slot
  • Create a new page and add a QmSliceWidget and rename it to sliceWidget
    • Go to Edit->Edit Signals/Slots (or press F4)
    • Connect sceneBrowserWidget::imageData(vtkImageData*) event to sliceWidget::SetImageData(vtkImageData*) slot
  • Create a new page and add a Qm(GPU)VolumeRenderWidget and rename it to volumeRenderWidget
    • Go to Edit->Edit Signals/Slots (or press F4)
    • Connect sceneBrowserWidget::imageData(vtkImageData*) event to sliceWidget::SetImageData(vtkImageData*) slot

Addin the QmStackedDisplayToolbarWidget

  • Select in the Maverick [Common Qt Widgets]: QmStackedDisplayToolbarWidget and place it where you want.
  • Rename it to stackedDisplayToolbarWidget
  • Go to Edit->Edit Signals/Slots (or press F4)
  • Connect stackedDisplayToolbarWidget::displayChanged(const char*) event to stackedDisplayWidget::ChangeIndexFromWidgetType(const char*)

Step 1: Creating a Load image step

Creating a new step in the workflow

in the Qt Designer

  • Select the workflowManager widget
  • Right click on it and select Insert Page after current Page. This is the standard way of adding steps in your workflow.
  • Put the description in the "accessibleDescription" field of the page

Connecting the OpenScene button

  • First create a push button and rename it loadScene and put the text you want as a label.
  • Go to Edit->Edit Signals/Slots (or press F4)
  • Connect loadScene::clicked() event to sceneWidget::openScene() slot

Step 2: Add a new Module as a workflow step

Adding and icon to my application

  1. Create the applications's icon and name it icon.ico
  2. Create an MyApplication.rc file and add this line
 IDI_ICON1               ICON    DISCARDABLE     "icon.ico"
  1. Add the MaverickAblaTx.rc in the list of source files in your CMakeLists.txt

Arranging the layout on the QmStackedDisplayWidget

In order to have the RenderWidgets span the whole page of the QmStackedDisplayWidget, from the Qt designer

  1. Select the page of the QmStackedDisplayWidget
  2. In the Property Editor -> Layout adjust the layoutLeftMargin,layoutRightMargin, layoutTopMargin and layoutBottomMargin.