Plots In Qt
Posted By admin On 11/04/22Tableau QT: Quadrant Plots I love Quadrants Plots as a quick way to segmenting your data, so please enjoy this Tableau Quick Tip (QT) which you can do in 5 mins or less. Designer is a graphical tool for building complex Qt4 GUI applications. In this post, I will use Designer to construct a simple GUI application, and in the following posts, I’ll use Python, matplotlib, and PyQt4 to add the necessary application logic to display an interactive data plot and a plot. Qwt is a mature, well-documented library and, I think it's fair to say, the standard solution for implementing plots and other display and control widgets in Qt. If you need 3D plots, try QwtPlot3D.
Designer is a graphical tool for building complex Qt4 GUI applications. In this post, I will use Designer to construct a simple GUI application, and in the following posts, I’ll use Python, matplotlib, and PyQt4 to add the necessary application logic to display an interactive data plot and a plot selection list. The final result is shown below.
One thing to keep in mind, Designer’s purpose is to help with GUI construction and widget layout. Application logic must be added in a separate step. That means that ultimately this example will differ from other Qt embedding examples in that we will end up with two files: the first, “window.ui”, defines our overall GUI design, and the second, “custommpl.py”, contains the custom application logic. A zip package of the completed files can be downloaded here.
Designing the Layout
A first step is to analyze the look of the GUI and decide how you will implement this with Designer. Although there are a number of ways to construct this layout, we will define a model that includes five major elements, with a generic graphical display shown below: 1) the main window holds everything together (black), 2) a list of figures (red), 3) a matplotlib container (blue), 4) a data plot (green), and 5) a navigation toolbar (purple).
There are two major layouts to consider in our application. First, the matplotlib container and figure list are horizontally aligned inside of the main window, with the figure list taking up less overall space. Second, the data plot and toolbar are vertically aligned inside of the matplotlib container.
With this list of widgets and layouts in hand, let’s try to create this application framework in Designer.
The Designer Window
Upon starting Designer, you will be presented with a creation dialog. Select “Main Window” and click “Create”. You should now see something very close to the screen shot shown below. The “Main Window” that we’ve just created is going to act as an overall application container widget, in other words the black box in the generic figure above.
This Designer window has four major elements that will be important for this tutorial.
- The blank, untitled “MainWindow” instance in the center of the screen is our application window. We will add widgets to this window to create our GUI layout. At this point, adjust the size of this window until it is approximately the size that you’d like to see for your final application.
- The “Widget Box” (left) contains all of the default Qt widgets that we can add to our MainWindow. To add a widget, click and drag the item into the MainWindow.
- The “Object Inspector” (top right) presents a tree of all the widgets that are currently present in our MainWindow. Use this to select and modify individual widgets. The Object indentation level indicates which widgets are contained inside other widgets. For example, the MainWindow widget currently contains centralwidget, menubar, and statusbar widgets.
- The “Property Editor”, just below the “Object Inspector”, is an editable list of properties for the currently selected widget.
Building the Framework
To start building our application, let’s add the two widgets that should be contained in the MainWindow: the figure list and the matplotlib container. To do this, drag and drop a “List Widget” (under Item Widgets) to the right side of the MainWindow and a generic Widget (under Containers) to the left hand side. These widgets will have some default size, which will not look correct.
Manual adjustment of the widgets size and position is unnecessary. This is done automatically by applying the appropriate layout to the MainWindow container widget. Right click on the MainWindow and select “Lay Out”. You can select either “Lay Out Horizontally” or “Layout in a Grid”, both of which will have the same effect.
This stretches both widgets until they completely fill the window; unfortunately, they will not be the correct shape. Size adjustments are made by changing several widget properties. First of all, select the List Widget (either by clicking on it in the MainWindow or selecting it from the Object Inspector) and set the following properties in the Property Editor:
- sizePolicy->Horizontal Policy->Maximum
- maximumSize->Width->200
Next, select the matplotlib container widget and set this property:
- sizePolicy->Horizontal Policy->Expanding
At this point, our application window should look very much like our final product. However, we still need to setup the contents of our matplotlib container widget.
Adding the data plot and toolbar to the matplotlib container is best done as part of the application logic, but a vertical alignment should be enforced for the widgets contained in the matplotlib container. Unfortunately, a little hack is necessary to set the layout inside our matplotlib container. First of all, drag and drop a temporary widget (it doesn’t matter what you choose) into the matplotlib container. Now right click on the matplotlib container and set the “Lay Out” to “Lay Out Vertically”. With the layout set, you can delete the temporary widget from the plotting widget container.
Naming the Widgets
As a final step, we are going to change the names of some of the application elements. Ultimately, this application framework is going to be compiled into a Python class, and each of the widget and layout elements will be added as attributes of this class. The default attribute names are very generic “widget”, “listWidget”, etc., and renaming these widgets in Designer changes the attribute names as defined inside the main window class. This is not strictly necessary, but it will probably make it easier to keep track of the elements in a much larger GUI application. The widget names are shown in the “Object” column of the “Object Inspector”. To change the names, simply double-click the name and type in the new one. For this application, make the following name changes:
- listWidget->mplfigs
- widget->mplwindow
The layouts are also named attributes of our application, and it will be useful to change at least the name of the vertical alignment layout of “mplwindow”. Select the “mplwindow” widget in the Object Inspector, and scroll through the properties until you find the “Layout” section. Change the layoutName property from “verticalLayout” to “mplvl”.
Saving the Application
With the application design complete, save this project as “window.ui”. UI files are language-agnostic XML representations of our GUI. If you need to make changes to your layout in the future, reopen the UI file with Designer and make the necessary changes. In the next post, we’ll go over how to programmatically extract out our MainWindow class from the UI file and create a subclass with the appropriate logic.
PyQt4 ships with a command line utility script called pyuic4
, which converts UI files into Python module files. Below is an example of the command line invocation of this script.
This is useful if you want to see how the MainWindow class and its attributes are defined in Python code; however, this step is unnecessary. Be Warned! Designer can not open Python module files, so you should never delete the UI file. Also, do not directly modify the resulting Python module. If you make layout changes to the UI file, the pyuic4
conversion process will overwrite your modified window module. To add additional logic to your MainWindow class, write a separate module file that defines a subclass of the MainWindow object. (See the next post.)
The QBoxPlotSeries class presents data in box-and-whiskers charts. More...
Header: | #include <QBoxPlotSeries> |
Instantiated By: | BoxPlotSeries |
Inherits: | QAbstractSeries |
Properties
|
|
Public Functions
QBoxPlotSeries(QObject *parent = nullptr) | |
virtual | ~QBoxPlotSeries() |
bool | append(QBoxSet *set) |
bool | append(QList<QBoxSet *> sets) |
bool | boxOutlineVisible() |
QList<QBoxSet *> | boxSets() const |
qreal | boxWidth() |
QBrush | brush() const |
void | clear() |
int | count() const |
bool | insert(int index, QBoxSet *set) |
QPen | pen() const |
bool | remove(QBoxSet *set) |
void | setBoxOutlineVisible(bool visible) |
void | setBoxWidth(qreal width) |
void | setBrush(const QBrush &brush) |
void | setPen(const QPen &pen) |
bool | take(QBoxSet *set) |
Reimplemented Public Functions
virtual QAbstractSeries::SeriesType | type() const override |
Signals
void | boxOutlineVisibilityChanged() |
void | boxWidthChanged() |
void | boxsetsAdded(QList<QBoxSet *> sets) |
void | boxsetsRemoved(QList<QBoxSet *> sets) |
void | brushChanged() |
void | clicked(QBoxSet *boxset) |
void | countChanged() |
void | doubleClicked(QBoxSet *boxset) |
void | hovered(bool status, QBoxSet *boxset) |
void | penChanged() |
void | pressed(QBoxSet *boxset) |
void | released(QBoxSet *boxset) |
Detailed Description
A box plot series acts as a container for box-and-whiskers items. Items from multiple series are grouped into categories according to their index value.
The QBarCategoryAxis class is used to add the categories to the chart's axis. Category labels have to be unique. If the same category label is defined for several box-and-whiskers items, only the first one is drawn.
See the box-and-whiskers chart example to learn how to create a box-and-whiskers chart.
See also QBoxSet and QBarCategoryAxis.
Property Documentation
boxOutlineVisible : bool
This property holds the visibility of the box outline.
Access functions:
bool | boxOutlineVisible() |
void | setBoxOutlineVisible(bool visible) |
Notifier signal:
boxWidth : qreal
This property holds the width of the box-and-whiskers item. The value indicates the relative width of the item within its category. The value can be between 0.0 and 1.0. Negative values are replaced with 0.0 and values greater than 1.0 are replaced with 1.0.
Access functions:
qreal | boxWidth() |
void | setBoxWidth(qreal width) |
Notifier signal:
brush : QBrush
This property holds the brush used to fill the boxes of the box-and-whiskers items.
Access functions:
QBrush | brush() const |
void | setBrush(const QBrush &brush) |
Notifier signal:
count : const int
This property holds the number of box-and-whiskers items in a box plot series.
Access functions:
int | count() const |
Notifier signal:
pen : QPen
This property holds the pen used to draw the lines of the box-and-whiskers items.
Access functions:
QPen | pen() const |
void | setPen(const QPen &pen) |
Notifier signal:
Member Function Documentation
QBoxPlotSeries::QBoxPlotSeries(QObject *parent = nullptr)
Constructs an empty box plot series that is a QObject and a child of parent.
[signal]
void QBoxPlotSeries::boxOutlineVisibilityChanged()
This signal is emitted when the box outline visibility changes.
Note: Notifier signal for property boxOutlineVisible.
[signal]
void QBoxPlotSeries::boxWidthChanged()
This signal is emitted when the width of the box-and-whiskers item changes.
Note: Notifier signal for property boxWidth.
[signal]
void QBoxPlotSeries::boxsetsAdded(QList<QBoxSet *> sets)
This signal is emitted when the list of box-and-whiskers items specified by sets is added to the series.
[signal]
void QBoxPlotSeries::boxsetsRemoved(QList<QBoxSet *> sets)
This signal is emitted when the list of box-and-whiskers items specified by sets is removed from the series.
[signal]
void QBoxPlotSeries::brushChanged()
This signal is emitted when the brush used to fill the boxes of the box-and-whiskers items changes.
Note: Notifier signal for property brush.
[signal]
void QBoxPlotSeries::clicked(QBoxSet *boxset)
This signal is emitted when the user clicks the box-and-whiskers item specified by boxset in the chart.
[signal]
void QBoxPlotSeries::countChanged()
This signal is emitted when the number of box-and-whiskers items in the series changes.
Note: Notifier signal for property count.
[signal]
void QBoxPlotSeries::doubleClicked(QBoxSet *boxset)
This signal is emitted when the user double-clicks the box-and-whiskers item specified by boxset in the chart.
[signal]
void QBoxPlotSeries::hovered(boolstatus, QBoxSet *boxset)
This signal is emitted when a mouse is hovered over the box-and-whiskers item specified by boxset in the chart. When the mouse moves over the item, status turns true
, and when the mouse moves away again, it turns false
.
[signal]
void QBoxPlotSeries::penChanged()
This signal is emitted when the pen used to draw the lines of the box-and-whiskers items changes.
Plots In Qts
Note: Notifier signal for property pen.
[signal]
void QBoxPlotSeries::pressed(QBoxSet *boxset)
This signal is emitted when the user clicks the box-and-whiskers item specified by boxset in the chart and holds down the mouse button.
[signal]
void QBoxPlotSeries::released(QBoxSet *boxset)
This signal is emitted when the user releases the mouse press on the box-and-whiskers item specified by boxset in the chart.
[virtual]
QBoxPlotSeries::~QBoxPlotSeries()
Removes the series from the chart.
bool QBoxPlotSeries::append(QBoxSet *set)
Qt Graph
Adds a single box-and-whiskers item specified by set to the series and takes ownership of it. If the item is null or it already belongs to the series, it will not be appended. Returns true
if appending succeeded.
bool QBoxPlotSeries::append(QList<QBoxSet *> sets)
Adds a list of box-and-whiskers items specified by sets to the series and takes ownership of them. If the list is null or the items already belong to the series, it will not be appended. Returns true
if appending succeeded.
QList<QBoxSet *> QBoxPlotSeries::boxSets() const
Returns a list of box-and-whiskers items in a box plot series. Keeps the ownership of the items.
void QBoxPlotSeries::clear()
Removes all box-and-whiskers items from the series and permanently deletes them.
int QBoxPlotSeries::count() const
Returns the number of box-and-whiskers items in a box plot series.
Note: Getter function for property count.
bool QBoxPlotSeries::insert(intindex, QBoxSet *set)
Inserts a box-and-whiskers item specified by set to a series at the position specified by index and takes ownership of the item. If the item is null or already belongs to the series, it will not be appended. Returns true
if inserting succeeds.
bool QBoxPlotSeries::remove(QBoxSet *set)
Removes the box-and-whiskers item specified by set from the series and permanently deletes it if the removal succeeds. Returns true
if the item was removed.
bool QBoxPlotSeries::take(QBoxSet *set)
Takes the box-and-whiskers item specified by set from the series. Does not delete the item.
Note: The series remains the item's parent object. You must set the parent object to take full ownership.
Returns true
if the take operation succeeds.
[override virtual]
QAbstractSeries::SeriesType QBoxPlotSeries::type() const
Reimplements an access function for property: QAbstractSeries::type.
Qt Draw Contour
Returns the type of the series.
See also QAbstractSeries and SeriesType.
Qt Spectrum Plot
© 2021 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.