blob: 9a66c26aca8eb22af66b530523b3abf0fc970414 [file] [log] [blame]
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the documentation of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:FDL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Free Documentation License Usage
** Alternatively, this file may be used under the terms of the GNU Free
** Documentation License version 1.3 as published by the Free Software
** Foundation and appearing in the file included in the packaging of
** this file. Please review the following information to ensure
** the GNU Free Documentation License version 1.3 requirements
** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
** $QT_END_LICENSE$
**
****************************************************************************/
/*!
\example itemmodel
\title Item Model Example
\ingroup qtdatavisualization_examples
\brief Using an item model as data source for Q3DBars.
The item model example shows how to make a simple 3D bar graph using Q3DBars and how to modify
the data being drawn at run-time. The example shows how to:
\list
\li Create an application with Q3DBars and widgets
\li Use QItemModelBarDataProxy to set data to the graph
\li Use a table widget to modify the data in the graph
\endlist
For instructions about how to interact with the graph, see \l{Qt Data Visualization Interacting with Data}{this page}.
\image itemmodel-example-2.png
\include examples-run.qdocinc
\section1 Creating the Application
First, in main.cpp, we create a QApplication, instantiate Q3DBars and a window container for it:
\snippet itemmodel/main.cpp 0
The call to QWidget::createWindowContainer is required, as all data visualization graph classes
(Q3DBars, Q3DScatter, and Q3DSurface) inherit QWindow. Any class inheriting QWindow cannot be used
as a widget any other way.
Then we'll create a layout and add the graph and the table widget into it:
\snippet itemmodel/main.cpp 1
The table widget is going to be used to display the numerical data being inserted into the
graph, and to modify it (See \l {Adding data to the graph} and \l {Interacting with the data}).
We need to instantiate QItemModelBarDataProxy and a QBar3DSeries for it, and give the series
to the graph:
\snippet itemmodel/main.cpp 2
Here we tell the proxy to directly map the model's rows and columns into the proxy's rows and
columns instead of defining row and column roles to map for them. Then we give the model from
the table widget to the proxy. We also create a series instance and set the proxy to it.
We customize the series visuals a bit by changing the object mesh to pyramids, and finally
add the series to the graph.
Next, let's create another class to handle the data addition and other interaction with the
graph. Let's call it \c GraphDataGenerator (See \l {Setting up the graph} and
\l {Adding data to the graph} for details) and connect some signals between QBar3DSeries,
\c GraphDataGenerator, and QTableWidget (See \l {Interacting with the data} for a closer look):
\snippet itemmodel/main.cpp 3
The application main is done and we can show the graph and start the event loop:
\snippet itemmodel/main.cpp 4
\section1 Setting up the Graph
Let's set up the visual attributes for the graph in the constructor of \c GraphDataGenerator:
\snippet itemmodel/main.cpp 5
\snippet itemmodel/main.cpp 6
\snippet itemmodel/main.cpp 7
First we set bar thickness ratio to 1.0, which means bars will be as wide as they are deep. 1.0
is also the default value, so the line is basically unnecessary. It's left there so you could
easily try how changing it affects the graph. The second line sets bar spacings to 0.2, which
means there will be a gap of 20% of the bar's thickness between the bars in both directions.
We want to be able to select rows of data for a closer inspection, so we set the selection mode
to slice item and row. This means that whenever we select a bar in the graph, the whole row will be
displayed separately and the selected bar will be highlighted.
We don't want to use the default colors, so we set one of the predefined themes as the active theme.
Next line sets the font to \c Impact. If your system doesn't have it, it will be replaced by
the system default.
And finally, we set the camera position to one of the predefined camera positions.
Now the initial graph settings are done.
\note You do not need to set any of these in case you're happy with the defaults. You can
easily try them by commenting out the contents of the constructor.
\section1 Adding Data to the Graph
We created the data generator in the application main and gave it the graph and the table
widget as parameters:
\code
GraphDataGenerator generator(graph, tableWidget);
\endcode
We added a separate start method to the generator, so that it wouldn't start doing anything
until everything else is set up. We then called the method when starting the application:
\code
generator.start();
\endcode
Let's have a look at the contents of the \c start() method:
\snippet itemmodel/main.cpp 8
The main thing \c start() does is set up the data model. It also activates a timer for getting
the accurate dimensions of the table widget after it's been filled with data. The reason we
do this is that the widget doesn't know its final visual domensions until all the data has been
inserted to it and it has been shown. The data timer usage is not vital for the
application, so we won't take a closer look at it. It's just there to make QTableWidget look better.
In \c setupModel() we first introduce the row and column labels, and the actual data:
\snippet itemmodel/main.cpp 9
Then we set up the axes:
\snippet itemmodel/main.cpp 10
Next we will set up the table widget:
\snippet itemmodel/main.cpp 11
After that all that's left is adding the data to the table widget:
\snippet itemmodel/main.cpp 12
Now we have a bar graph and a table widget, both displaying the same data.
You're probably wondering how the data can be displayed in the graph, as the only thing we did
was add it to the table widget? That's because of what we did earlier, in the application main:
\snippet itemmodel/main.cpp 2
We created QItemModelBarDataProxy instance, and gave the proxy the model of the table widget
we just created. The proxy maps the rows and the columns in the model of the table widget into
rows and columns for itself directly, as we set the QItemModelBarDataProxy::useModelCategories
property to true, and the graph gets the data to be displayed via the series that owns the proxy.
\section1 Interacting with the Data
We made a couple of signal connections in the application main earlier:
\snippet itemmodel/main.cpp 3
Now we'll find out what these were for.
The first one connects a signal from Q3DBars to the \c GraphDataGenerator. Signal
QBar3DSeries::selectedBarChanged() is emitted when a bar is selected from the series. We connect
that to a method in the data generator that selects the same data item in the table widget:
\snippet itemmodel/main.cpp 13
The second connection does the opposite; it connects a signal from the table widget to a
method in the data generator. The method then selects the corresponding bar in the series:
\snippet itemmodel/main.cpp 14
You can even select an item in the widget and change the value of it, and the new value is
updated to the graph. This is handled again by the proxy with mapping between the data
in the table widget and itself.
\image itemmodel-example.png
\section1 Example Contents
*/