|
|
(8 intermediate revisions by the same user not shown) |
Line 1: |
Line 1: |
− | [[Slicer3:Developers:Projects:QtSlicer|QtSlicer]]/[[Slicer3:Developers:Projects:QtSlicer/Tutorials|Tutorials]]← | + | This page has moved to [[Slicer4:Developers:Projects:QtSlicer/Tutorials/WidgetWriting|Slicer4 Widget Writing]] |
− | =Creating a custom widget in Slicer=
| |
− | ==Intro==
| |
− | A custom widget is a specialization of another widget or a group of widgets working together. Custom widgets are usually created when you need to add new functionality to existing widgets or groups of widgets. If you simply want a collection of widgets in a special configuration it can be easily done in QtDesigner and probably doesn't require to be a custom widget.
| |
− | | |
− | In the following we will assume you are familiar with Qt.<br>
| |
− | Here are some useful links:
| |
− | *http://doc.trolltech.com/how-to-learn-qt.html
| |
− | *http://doc.trolltech.com/object.html
| |
− | *http://doc.trolltech.com/properties.html
| |
− | | |
− | ==Before starting==
| |
− | There are 2 directories where custom widgets can be. You first have to decide in what directory your custom widget should go:
| |
− | *<i>Slicer3/Libs/qCTKWidgets</i>: Qt only widget
| |
− | *<i>Slicer3/Libs/qMRMLWidgets</i>: MRML-aware widgets
| |
− | A good practice is to split (if possible) your custom widget in 2 widgets, a QT-only widget, and a MRML-aware widget. The MRML widget inherits from the Qt only widget.<br>
| |
− | It is important to keep the widgets basic. If you think someone else can use your custom widget differently, or if someone would need less features than the custom widget currently have, it is probably a good idea to split the widget in 2 widgets linked with an IS-A relationship.<br>
| |
− | | |
− | ==Coding style==
| |
− | The name of the custom widgets must follow the pattern: <code>q[CTK|MRML][customName][baseQtWidget]</code>, where <code>baseQtWidget</code> is the name of the qt widget your custom widget inherits from (i.e. ComboBox, Slider, Dialog, Widget...), and <code>customName</code> is a descriptive name. Examples:
| |
− | *<code>qCTKCollapsibleGroupBox</code>
| |
− | *<code>qMRMLLinearTransformSlider</code>
| |
− | *<code><s>qCTKColorPicker</s></code><code>qCTKColorPickerButton</code>, <code>qCTKColorPickerDialog</code>
| |
− | | |
− | ==Note==
| |
− | *When you create your widget, make sure you highly use the [http://doc.trolltech.com/4.5/properties.html Qt property system], it let you customize your widgets from the Qt Designer.
| |
− | *The process to create a custom widget is similar for qCTKWidgets and qMRMLWidgets, this is why we will use the notation <b>q***Widgets</b> to describe either <b>qCTKWidgets</b> or <b>qMRMLWidgets</b>.
| |
− | | |
− | ==Step by step==
| |
− | *Create your widget files (.h and .cxx) in the <i>Lib/q***Widgets</i> directory.
| |
− | **If you use a <i>.ui</i> file, add it in the <i>Libs/q***Widgets/Resources/UI</i> directory
| |
− | **If you use icon files, add them in the <i>Libs/q***Widgets/Resources/Icons</i> directory and update the <i>Libs/q***Widgets/Resources/q***Widgets.qrc</i> file accordingly
| |
− | *Update the <i>Libs/q***Widgets/CMakeLists.txt</i> file with your widget files.
| |
− | ** add the <i>.h</i> and <i>.cxx</i> files in the <code>q***Widgets_SRCS</code> variable
| |
− | ** add the <i>.h</i> file in the <code>q***Widgets_MOC_SRCS</code> variable
| |
− | ** if any, add the <i>.ui</i> file in the <code>q***Widgets_UI_SRCS</code variable
| |
− | * compile with your favorite compiler.
| |
− | Congratulations, you just added a custom widget in Slicer. The widget can now be used anywhere in Slicer.<br>
| |
− | However the widget doesn't show up in QDesigner, let's create the custom widget plugin for QDesigner.
| |
− | | |
− | =Create a widget for the designer=
| |
− | For a general presentation to create custom widgets for Qt Designer, see http://doc.trolltech.com/designer-creating-custom-widgets.html
| |
− | ==Step by step==
| |
− | *Copy paste this template in the <i>Libs/q***Widgets/Plugins</i> directory.
| |
− | {|
| |
− | !qCTKWidget
| |
− | !qMRMLWidget
| |
− | |-
| |
− | |<pre>
| |
− | #ifndef __qCTKCustomWidgetPlugin_h
| |
− | #define __qCTKCustomWidgetPlugin_h
| |
− | | |
− | #include "qCTKWidgetsBasePlugin.h"
| |
− | #include "qCTKWidgetsPluginWin32Header.h"
| |
− | | |
− | class QCTK_WIDGETS_PLUGIN_EXPORT qCTKCustomWidgetPlugin : public QObject,
| |
− | public qCTKWidgetsBasePlugin
| |
− | {
| |
− | Q_OBJECT
| |
− | | |
− | public:
| |
− | qCTKCustomWidgetPlugin(QObject *_parent = 0);
| |
− |
| |
− | QWidget *createWidget(QWidget *_parent);
| |
− | QString domXml() const;
| |
− | QString includeFile() const;
| |
− | bool isContainer() const;
| |
− | QString name() const;
| |
− |
| |
− | };
| |
− | | |
− | #endif
| |
− | | |
− | </pre>
| |
− | Name the file <i>qCTK[name of your widget]Plugin.h</i>
| |
− | |<pre>
| |
− | #ifndef __qMRMLCustomWidgetPlugin_h
| |
− | #define __qMRMLCustomWidgetPlugin_h
| |
− | | |
− | #include "qMRMLWidgetsBasePlugin.h"
| |
− | #include "qMRMLWidgetsPluginWin32Header.h"
| |
− | | |
− | class QMRML_WIDGETS_PLUGIN_EXPORT qMRMLCustomWidgetPlugin : public QObject,
| |
− | public qMRMLWidgetsBasePlugin
| |
− | {
| |
− | Q_OBJECT
| |
− | | |
− | public:
| |
− | qMRMLCustomWidgetPlugin(QObject *_parent = 0);
| |
− |
| |
− | QWidget *createWidget(QWidget *_parent);
| |
− | QString domXml() const;
| |
− | QString includeFile() const;
| |
− | bool isContainer() const;
| |
− | QString name() const;
| |
− |
| |
− | };
| |
− | | |
− | #endif
| |
− | | |
− | </pre>
| |
− | Name the file qMRML[name of your widget]Plugin.h
| |
− | |}
| |
− | *Replace <i>CustomWidget</i> by the name of your widget
| |
− | *Copy paste this template in the <i>Libs/q***Widgets/Plugins</i> directory.
| |
− | {|
| |
− | !qCTKWidgets
| |
− | !qMRMLWidgets
| |
− | |-
| |
− | |<pre>
| |
− | #include "qCTKCustomWidgetPlugin.h"
| |
− | #include "qCTKCustomWidget.h"
| |
− | | |
− | qCTKCustomWidgetPlugin::qCTKCustomWidgetPlugin(QObject *_parent)
| |
− | : QObject(_parent)
| |
− | {
| |
− | | |
− | }
| |
− | | |
− | QWidget *qCTKCustomWidgetPlugin::createWidget(QWidget *_parent)
| |
− | {
| |
− | qCTKCustomWidget* _widget = new qCTKCustomWidget(_parent);
| |
− | return _widget;
| |
− | }
| |
− | | |
− | QString qCTKCustomWidgetPlugin::domXml() const
| |
− | {
| |
− | return "<widget class=\"qCTKCustomWidget\" \
| |
− | name=\"CTKCustomWidget\">\n"
| |
− | "</widget>\n";
| |
− | }
| |
− | | |
− | QString qCTKCustomWidgetPlugin::includeFile() const
| |
− | {
| |
− | return "qCTKCustomWidget.h";
| |
− | }
| |
− | | |
− | bool qCTKCustomWidgetPlugin::isContainer() const
| |
− | {
| |
− | return false;
| |
− | }
| |
− | | |
− | QString qCTKCustomWidgetPlugin::name() const
| |
− | {
| |
− | return "qCTKCustomWidget";
| |
− | }
| |
− | </pre>
| |
− | Name the file <i>qCTK[name of your widget]Plugin.cxx</i>
| |
− | |<pre>#include "qMRMLCustomWidgetPlugin.h"
| |
− | #include "qMRMLCustomWidget.h"
| |
− | | |
− | qMRMLCustomWidgetPlugin::qMRMLCustomWidgetPlugin(QObject *_parent)
| |
− | : QObject(_parent)
| |
− | {
| |
− | | |
− | }
| |
− | | |
− | QWidget *qMRMLCustomWidgetPlugin::createWidget(QWidget *_parent)
| |
− | {
| |
− | qMRMLCustomWidget* _widget = new qMRMLCustomWidget(_parent);
| |
− | return _widget;
| |
− | }
| |
− | | |
− | QString qMRMLCustomWidgetPlugin::domXml() const
| |
− | {
| |
− | return "<widget class=\"qMRMLCustomWidget\" \
| |
− | name=\"MRMLCustomWidget\">\n"
| |
− | "</widget>\n";
| |
− | }
| |
− | | |
− | QString qMRMLCustomWidgetPlugin::includeFile() const
| |
− | {
| |
− | return "qMRMLCustomWidget.h";
| |
− | }
| |
− | | |
− | bool qMRMLCustomWidgetPlugin::isContainer() const
| |
− | {
| |
− | return false;
| |
− | }
| |
− | | |
− | QString qMRMLCustomWidgetPlugin::name() const
| |
− | {
| |
− | return "qMRMLCustomWidget";
| |
− | }</pre>
| |
− | | |
− | Name the file qMRML[name of your widget]Plugin.cxx
| |
− | |}
| |
− | *Replace <i>CustomWidget</i> by the name of your widget
| |
− | *If the widget is a container, return true in the method <code>isContainer()</code>. See <i>qCTKCollapsibleWidgetPlugin.cxx</i> for more information.
| |
− | *You can customize how the widget look in the designer by modifying the <code>domxml()</code> method.
| |
− | *Update the <i>Libs/q***Widgets/Plugins/CMakeLists.txt</i> file with your widget files.
| |
− | ** add the <i>.h</i> and <i>.cxx</i> files in the <code>q***WidgetsPlugin_SRCS</code> variable
| |
− | ** add the <i>.h</i> file in the <code>q***WidgetsPlugin_MOC_SRCS</code> variable
| |
− | ** if any, add the extension files as well. i.e. <i>qCTKCollapsibleWidgetContainerExtension.cxx</i>
| |
− | *Add your widget in the <code>q***WidgetsPlugins::customWidgets()</code> method in the <i>Libs/q***Widgets/Plugins/q***WidgetsPlugins.h</i> file
| |
− | *compile
| |
− | Congratulations, you just added a custom widget in a plugin that can be read by QDesigner. Read the [[Slicer3:Developers:Projects:QtSlicer:Tutorials:QtDesigner|next tutorial]] to learn how you can use the widget into Qt Designer.
| |
− | '''Coding style:'''
| |
− | For a better code visibility, make sure you respect the alphabetical order in the <i>CMakeLists.txt</i> files when you add your files in the CMake variables.<br>
| |