.. role:: raw-html(raw)
:format: html
=========
Tutorials
=========
In this section, general guidelines about developing PyQt application with
``mpl4qt`` will be addressed, starting the development with the following
applications:
* :ref:`Random X-Y curve plotter`
Designer
--------
``designer`` is a user-friendly GUI application to help the developer to build
UI painlessly, in a WYSIWYG way. The created UI file from ``designer`` is
structured XML file, which could be parsed by Qt libraries to show the UI in
the Qt applications, however, it is designed for both C++ and Python, so if
you're working on the PyQt application, another command named ``pyuic5`` could
be used to convert the UI file into Python module, which could be imported by
your PyQt application. There is a way that at the runtime, the UI file could be
loaded into to render the GUI, but it is recommended that always converting
UI file to Python module before runtime, since there might be chances that
different PyQt versions would be applied between development and runtime.
After installing ``mpl4qt``, simply type ``run_designer`` in the Linux
terminal to launch designer:
.. image:: ../images/designer_startup.png
:align: center
:width: 800px
As one can see, in the *Widget Box* column, a new category of so-called
*DataViz Widgets* is shown, inside which there is one widget called
*MatplotlibCurveWidget*, which is ready to be dragged&dropped.
.. warning::
If the following error message happens: *qtcore.so: undefined symbol: pyslice_adjustindices*, could be resolved by uninstalling pyqt5 package by ``pip uninstall pyqt5``, and installing the OS distributed one, see :ref:`Install mpl4qt `.
.. _Random X-Y curve plotter:
Random X-Y Curve Plotter
------------------------
**What does this application do?** This app will make the most of
*MatplotlibCurveWidget*, to show how the figure properties could be controlled
interactively, and how the curve could be updated.
Create a New Application
^^^^^^^^^^^^^^^^^^^^^^^^
In the designer, click the *New icon* in the toolbar or menu
:raw-html:`File` :raw-html:`→` :raw-html:`New`
or :raw-html:`Ctrl` + :raw-html:`N` to create a new project for the
new application:
.. image:: ../images/app1_01.png
:align: center
:width: 800px
One can choose *Screen Size*, but leave it as Default size is OK, the size
could be adjusted later, click *Create* button will lead you to the form
workspace. Adjust the form size by dragging the form border.
Place Widgets
^^^^^^^^^^^^^
All the widgets in the *Widget Box* column could be dragged and dropped to
the form space to serve with different purposes, e.g. the *Label* usually
is used to provide the static indication. So we can place a title with *Label*:
drag the *Label* icon from *Widget Box* to the form workspace, double-click
to name it as *Random X-Y Curve Plotter*, and in the *Property Editor* column,
simply check out some items to make it look better, e.g. set *Point Size* as
20, check *Bold*, just as the following image shows:
.. image:: ../images/app1_02.png
:align: center
:width: 800px
Next, place the *MatplotlibCurveWidget* into the workspace in the same way,
and one button for random curve generation, change the button text to *Update*.
After that, you'll get something like this:
.. image:: ../images/app1_03.png
:align: center
:width: 800px
Inside the *designer*, the initial widget configuration could be edited through
*Property Editor* column, e.g. this is the list for *MatplotlibCurveWidget*:
.. image:: ../images/curve_plist.png
:align: center
:width: 300px
Inspect MatplotlibCurveWidget
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Before moving forward, let's first take a look at what does *MatplotlibCurveWidget* provide, a good way to know is to run this app. Yes, the app is just ready
to run.
Save this project by clicking *Save icon* in the toolbar or
:raw-html:`Ctrl` + :raw-html:`S`, locate
and name it as *ui_app1.ui*, check out to the location where the ui file is,
in the terminal, run the following command to convert ui file to Python module:
.. code-block:: python
pyuic5 ui_app1.ui -o ui_app1.py -x
You'll get a new Python file generated from ui file, simply run with
``python3 ui_app1.py``, a window will pop up:
.. image:: ../images/app1_04.png
:align: center
:width: 500px
The *MatplotlibCurveWidget* is designed with the ability to change the
figure properties via the context menu, by right-clicking in the figure,
choose *Config* item will guide you to a popup dialog, close it by hitting
*ESC* or clicking *Close* in the windows title bar.
Here is the list of available options could be controlled via *Config* menu,
just name as a few: line color, line style, line width, marker size, marker
style, marker color, labels, as well as fonts, grid, layout, etc.
.. image:: ../images/config01.png
:align: center
:width: 400px
.. image:: ../images/config02.png
:align: center
:width: 400px
.. image:: ../images/config03.png
:align: center
:width: 400px
Edit Signal/Slot
^^^^^^^^^^^^^^^^
Inside *designer*, signal and slot could be easily connected to implement
features, e.g. let's add one *Double Spin Box* to control the line with.
Just like the following image shows:
.. image:: ../images/app1_05.png
:align: center
:width: 800px
Then go to *Signal/Slot Editor*, connect the *valueChanged(double)* signal
of *doubleSpinBox* to *setLineWidth(double)* slot of *matplotlibcurveWidget*:
.. image:: ../images/app1_06.png
:align: center
:width: 800px
Save and convert ui file again, run to see the changes.
Implement Additional Features
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
*MatplotlibCurveWidget* features a lot of functionality that could be
implemented via Qt's signal and slot mechanism [#f1]_.
Some of them could be achieved in *designer*, but some are not,
see :ref:`dev_slots`.
One of the additional
fundamental ones is to update the curve, e.g. the *Update* should be
used as the trigger for curve updating, every clicking, here, the curve
would be updated with a new sine curve with random noise.
The slot
:py:meth:`~mpl4qt.widgets.mplcurvewidget.MatplotlibCurveWidget.setYData` could
be used to update the y data of the curve, generally, connecting with
a PyQt signal to this slot will make this happen. However, before writing
some code to the generated Python module, one thing should keep in mind,
that is usually the updating will not be applied directly to that Python file
in place, but by extending it, here is how to accomplish:
Create a new file named as, for instance, ``app1.py``, and inherit the class
which renders the UI, then extend within the new class:
.. literalinclude:: ../snippets/app1.py
:language: python
:linenos:
One can note how the signal and slot mechanism works:
1. Define your PyQt signal;
2. Connect the signal to the specific slot;
3. Emit the signal when needed.
In this example, the signal named ``yDataChanged`` is created with data type
of ``QVariant``, then connected with ``setYData`` slot of
*matplotlibcurveWidget*; next, the ``clicked`` signal is connected with the
defined slot ``update_ydata``, in which new y data is generated and emitted.
Run this app by ``python3 app1.py``, and click ``Update`` button to see the
updating curve, and change the figure property when needed, e.g. check
*Auto Scale* on and off (see below), to see the what happen.
.. image:: ../images/update.gif
:align: center
:width: 500px
Extended
^^^^^^^^
*matplotlibcurveWidget* also supports multiple curves visualization by the slot
:py:meth:`~mpl4qt.widgets.mplcurvewidget.MatplotlibCurveWidget.add_curve`.
Currently, multiple curves are managed by line ID, the first curve is of line
ID 0, the second one is of line ID 1, and so on. Every time `add_curve`, the
current line ID will be set of the new added one, so switching line ID is
required to do the data updating for other lines, by
:py:meth:`~mpl4qt.widgets.mplcurvewidget.MatplotlibCurveWidget.setLineID` slot.
.. image:: ../images/app1-extended.png
:align: center
:width: 500px
Below is an extended version of ``app1.py``, which supports more operations.
.. literalinclude:: ../snippets/app1-extended.py
:language: python
:linenos:
The full working example could be downloaded from
:download:`here <../snippets/app1.tar.bz2>`.
BarChart Plot Example
---------------------
**What does this application do?** This app will visualize the data with bar
chart plot by using *MatplotlibBarWidget*.
The following snippet shows how to use this widget:
.. literalinclude:: ../snippets/test_barplot.py
:language: python
:linenos:
The full working example could be downloaded from
:download:`here <../snippets/app2.tar.bz2>`.
Stem Plot Example
-----------------
**What does this application do?** This app will demonstrate how to use *MatplotlibErrorbarWidget*
to visualize data in a stem plot style.
.. image:: ../images/stemPlotEmulation.png
:align: center
:width: 800px
The following snippet shows how to use this widget:
.. literalinclude:: ../snippets/stem_emulation.py
:language: python
:linenos:
The full working example could be downloaded from
:download:`here <../snippets/stemEmulation.zip>`.
.. only:: html
.. rubric:: Footnotes
.. [#f1] http://doc.qt.io/qt-5/signalsandslots.html