summaryrefslogtreecommitdiffstats
path: root/examples/bars/doc/src/bars.qdoc
blob: a8de709b1b62c8c3a68670d85fdfec77b930a8f7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc
** All rights reserved.
** For any questions to Digia, please use contact form at http://qt.digia.com
**
** This file is part of the QtDataVisualization module.
**
** Licensees holding valid Qt Enterprise licenses may use this file in
** accordance with the Qt Enterprise License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.
**
** If you have questions regarding the use of this file, please use
** contact form at http://qt.digia.com
**
****************************************************************************/

/*!
    \example bars
    \title Bars Example
    \ingroup qtdatavisualization_examples
    \brief Using an item model as data source for Q3DBars.

    The bars 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 How to create an application with Q3DBars and widgets
        \li How to use QItemModelBarDataMapping and QItemModelBarDataProxy to set data to the graph
        \li How to use a table widget to modify the data in the graph
    \endlist

    \image bars-example-2.png

    \section1 Creating the application

    First, in main.cpp, we create a QApplication, instantiate Q3DBars and a window container for it:

    \snippet ../examples/bars/main.cpp 0

    The call to QWidget::createWindowContainer is required, as all data visualization types
    (Q3DBars, Q3DScatter, 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 ../examples/bars/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 QItemModelBarDataMapping and QItemModelBarDataProxy and give them to the
    graph:

    \snippet ../examples/bars/main.cpp 2

    Here we tell the mapping object to directly map model's rows and columns into 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 and the mapping object to the proxy. Finally we set the proxy as the active
    data proxy for the graph.

    Next, let's create another class to handle the data addition and other interaction with the
    graph. Let's call it GraphDataGenerator (See \l {Setting up the graph} and
    \l {Adding data to the graph} for details) and connect some signals between Q3DBars,
    GraphDataGenerator and QTableWidget (See \l {Interacting with the data} for a closer look):

    \snippet ../examples/bars/main.cpp 3

    The application main is done and we can show the graph and start the event loop:

    \snippet ../examples/bars/main.cpp 4

    \section1 Setting up the graph

    Let's set up the visual attributes for the graph in the constructor of GraphDataGenerator:

    \snippet ../examples/bars/main.cpp 5
    \snippet ../examples/bars/main.cpp 6
    \snippet ../examples/bars/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.

    Then, we set the bar type to flat pyramids, overriding the default bar type.
    We want to be able to select rows of data for a closer inspection, so we set the selection mode
    to slice row. This means that whenever we select a bar in the graph, the whole row will be
    displayed separately.

    Next line sets the font to \c Impact. If your system doesn't have it, it will be replaced by
    system default.

    And finally, we set theme to \c Digia and camera position to \c {Preset Front}. 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 ../examples/bars/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 whole data timer implementation is not vital for the
    application, so we won't take a closer look at it. It's just there to make the table look better.

    In \c setupModel() we first introduce the row and column labels, and the actual data:

    \snippet ../examples/bars/main.cpp 9

    Then we set up the axes:

    \snippet ../examples/bars/main.cpp 10

    The other lines there are pretty self-explanatory except for the one with the segment count.
    We're setting it to five as we want the value axis (the Y-axis) to show more values than just
    the lowest and the highest.

    Next we will set up the table widget:

    \snippet ../examples/bars/main.cpp 11

    After that all that's left is adding the data to the table widget:

    \snippet ../examples/bars/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 ../examples/bars/main.cpp 2

    We created QItemModelBarDataMapping and QItemModelBarDataProxy instances, and gave the proxy
    the model of the table widget and the model mapping we just created. Then we set the proxy as
    the active proxy for the graph. The proxy maps the rows and the columns in the model of the table
    widget into rows and columns for itself using the model mapping, and the graph gets the data
    to be displayed from its active proxy.

    \section1 Interacting with the data

    We made a couple of signal connections in the application main earlier:

    \snippet ../examples/bars/main.cpp 3

    Now we'll find out what these were for.

    The first one connects a signal from Q3DBars to the GraphDataGenerator. Signal
    Q3DBars::selectedBarPosChanged() is emitted when a bar is selected from the graph. We connect
    that to a method in the data generator that selects the same data item in the table widget:

    \snippet ../examples/bars/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 graph:

    \snippet ../examples/bars/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 active proxy with mapping between the data
    in the table widget and itself.

    \image bars-example.png

    \section1 Example contents
*/