|
|
Line 1: |
Line 1: |
| 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.
| |