Maverick/Creating your first application
From KitwarePublic
< Maverick
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:
- CMakeLists.txt: configuration file for CMake
- main.cxx: which starts the application
- MyApplicationUI.ui: Qt Designer file (should not be edited by hand)
- MyApplicationUI.h: derived class from the Qt MyApplicationUI application class
- 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
- Create the applications's icon and name it icon.ico
- Create an MyApplication.rc file and add this line
IDI_ICON1 ICON DISCARDABLE "icon.ico"
- 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
- Select the page of the QmStackedDisplayWidget
- In the Property Editor -> Layout adjust the layoutLeftMargin,layoutRightMargin, layoutTopMargin and layoutBottomMargin.