Commit 3253360f authored by Jean-Loup Haberbusch's avatar Jean-Loup Haberbusch
Browse files

ADDED Qt Widget wizard

parent 7d6c4494
Pipeline #15654 passed with stages
in 25 seconds
CamiTK wizard is a great tool to get you started quickly implementing an
algorithm on image volumes, meshes or other custom data structures. Yet,
there are a few restrictions of using the wizard. Among them, the
inability to use the power of Qt UI widgets in the current CamiTK wizard
(version 3.1) is a major one. By using the CamiTK wizard we could only
use 3 standard data types (bool, double and int) and 7 Qt data types
(QColor, QDate, QPoint, QPointF, QString and QVector3D) as input
variables. In this tutorial you will learn how to add Qt Widgets as
additional action parameters for actions created using the CamiTK
wizard.
There are two main ways of getting this done.
- [By coding-in the required functionality of Qt Widgets
yourself](/#Method_01:_By_coding-in_the_required_functionality_of_Qt_Widgets_yourself "wikilink")
- [By using the Qt
Designer](/#Method_02:_By_using_the_Qt_Designer "wikilink")
The two options have their own pros and cons which will be discussed in
their respective sections.
## Prerequivisites
It is assumed that you already have a working knowledge about the use of
CamiTK for development purposes and that you know how to create an
action using the CamiTK wizard. If not, please come back after following
[this tutorial](/Create_your_own_custom_action_for_CamiTK "wikilink") on
creating an action using the CamiTK wizard.
## Learning by doing
The tutorial will be presented by the use of an example action. Let’s
assume we want to provide an action where we want to achieve two main
goals.
- Change the output type from the input type
- Change the size of the output
These features will help to reduce a very large input (image volume/mesh
or something else) into a manageable output. As an example a DICOM image
volume of size 512 x 512 x 400 of signed short type can be reduced to an
image volume of size 128 x 128 x 400 of unsigned char type, effectively
reducing the size of the input by a factor of 32 (of course at the cost
of losing valuable information). Let’s call this action “Resampling
Action”.
To represent the output type we will use a combo box and populate it
with 6 enums (Same As Input,Char, Unsigned Char, Short, Unsigned Short,
Int and Unsigned Int).
[center|Combo box enums scalar type](/File:List_box2.png "wikilink")
To represent the output sizes we will use three spin boxes with a
default value of 256.
[center|Spin boxes of ouptut size](/File:Input_box.png "wikilink")
As you have already guessed, we can’t use CamiTK wizard to generate any
of these three Qt types (QComboBox, QEnum or QSpinBox). Hence we will
generate the new Resample action using the CamiTK wizard without
specifying any input parameters. The source files generated by the
CamiTK wizard can be found here.
The following is the dock widget that belongs to the action. As you can
see, there are no input parameters created by the wizard since we didn’t
ask it to create any.
[center|250px|Action overview with no
widget](/File:Resampling_action_overview_no_widget.png "wikilink")
Let’s get started with creating our Qt widgets to set the input
parameters.
## Method 01: By coding-in the required functionality of Qt Widgets yourself
The advantage of using QT properties is that the action will be for sure
used in the script feature of CamiTK, which might not be the case with
QT widget (.ui file) However you might not design very precisely your
action parameters (size, position and so on..), and some widgets might
not be available with this method.
### Spin Box
To get an spin box, with the label " *Size X (nb of Voxels)* ", and with
256 as a default value, you just have to add the line
```c++
setProperty("Size X (nb of Voxels)", QVariant(256));
```
in the constructor of your action, which is in a file ResampleAction.cpp
for example. You don’t need to add things in the .h file. When you
compile then you have the result as shown at the end of the paragraph.
Your action constructor should look like this
:
```c++
ResampleAction::ResampleAction(ActionExtension * extension) : Action(extension) {
/*
* Set the name and description of your action before...
*/
setProperty("Size X (nb of Voxels)", QVariant(256));
setProperty("Size Y (nb of Voxels)", QVariant(256));
setProperty("Size Z (nb of Voxels)", QVariant(256));
```
### Combo box
To get a combo box, it is a little bit longer: you have to modify both
the .h and .cpp file. The idea is to define a enumeration in the .h file
and add also a new data member in the class, that corresponds to the
label of your widget.
**Modifications on .h file:**
- Define in the public section an enumeration corresponding to the
different values of your list box :
```c++
enum Enum_Scalar_Type{ SameAsInput, UnsignedChar, Char, UnsignedShort, Short, UnsignedInt, Int};
```
- Define a data member in the private section, which is the type of
your enumeration. For our example, we would put
```c++
Enum_Scalar_Type Scalar_Type;
```
- Define a setter and a getter that will set and get the value of the
data member. This functions must be in the public part.
<!-- end list -->
```c++
Enum_Scalar_Type getScalarType();
void setScalarType(Enum_Scalar_Type Scalar_Type);
```
- Define the following QT Macros at the top of the class :
<!-- end list -->
```c++
Q_OBJECT
Q_ENUMS(Enum_Scalar_Type)
Q_PROPERTY( Enum_Scalar_Type Scalar_Type READ getScalarType WRITE setScalarType)
```
Finally your .h file should look like this :
```c++
class ResampleAction : public camitk::Action {
Q_OBJECT
Q_ENUMS(Enum_Scalar_Type)
Q_PROPERTY( Enum_Scalar_Type Scalar_Type READ getScalarType WRITE setScalarType)
public:
enum Enum_Scalar_Type{ SameAsInput, UnsignedChar, Char, UnsignedShort, Short, UnsignedInt, Int};
/// Default Constructor
ResampleAction(camitk::ActionExtension *);
/// Default Destructor
virtual ~ResampleAction();
/// Setter and Getter
Enum_Scalar_Type getScalarType();
void setScalarType(Enum_Scalar_Type Scalar_Type);
public slots:
virtual ApplyStatus apply();
private:
Enum_Scalar_Type Scalar_Type;
virtual void process(camitk::ImageComponent *);
};
```
**Modifications on .cpp file:**
- In your constructor, define the default value of your list box. For
example we should put “SameAsInput” :
```c++
this->Scalar_Type = SameAsInput;
```
- Define the setter and the getter functions :
```c++
ResampleAction::Enum_Scalar_Type ResampleAction::getScalarType() { return this->Scalar_Type;}
void ResampleAction::setScalarType(ResampleAction::Enum_Scalar_Type Scalar_Type) {
this->Scalar_Type = Scalar_Type;}
```
### What should I see ?
The result you will have should look like this :
[center | Result with Qt
properties](/File:Action_overview.png "wikilink")
### How to get the user’s inputs ?
To get the users input, it depends on which widget you have. If you have
defined a **spin box**, then you will have to call the function
```c++
property("Name of your label").toDouble();
```
and load the return of the function in a variable. You can obviously use
the toInt() or toFloat function to convert the input value in the type
you want.
If you have defined a **combo box**, then use the already defined getter
class member.
## Method 02: By using the Qt Designer
For you information, QtDesigner is
[WYSIWYG](http://en.wikipedia.org/wiki/WYSIWYG) application to easily
design Qt interface.
- Go to the your action class **.cpp** file.
- Find the **getWidget()** method. This method is called by the action
viewer to display the user interface.
<!-- end list -->
```c++
QWidget * myAction::getWidget() {
return NULL;
}
```
By default this one doesn’t return anything (NULL), thus the action
viewer doesn’t display anything. You will learn how to change this code
to display a new user interface for your action within the action
viewer.
- Open **QtDesigner** and create a new component inherited from the
QWidget class.
[thumb | center |450px | Select **Widget** in the dialog
box](/File:create_action_7.png "wikilink")
- Save this file under a **.ui** extension file in your action project
folder. Note, in the source directory, not the build one.
- Re configure your project using **CMake**. It will automatically
detect this **.ui** file and will generate a Qt Meta Object (moc)
file, needed to correctly map the user designed (.ui) file with a
corresponding c++ file.
- Reopen your project in your IDE, you normally have an new header
file of the same name of your **.ui** designed interface. This file
is now automatically generated when compiling your project. You will
include this file in your code to consider the interface designed
using **QtDesigner**.
- Include this file and declare an instance of it in your action class
(thus you can get access to its declared components).
This reference will let you communicating within your code to any
**QtDesigner** designed components of your interface.
Finally you can easily control your CamiTK action. Simply edit your
**.ui** interface file using **QtDesigner**. And create the
corresponding components c++ functions in your action class.
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment