summaryrefslogtreecommitdiffstats
path: root/examples
diff options
context:
space:
mode:
authorTomi Korpipää <tomi.korpipaa@digia.com>2013-10-08 10:12:57 +0300
committerTomi Korpipää <tomi.korpipaa@digia.com>2013-10-08 10:15:58 +0300
commit0daa4359bdaba6372bc8235550892afdef003120 (patch)
tree1988ddb4cafaec5a927d3ad515a598fab0daab25 /examples
parent8d8a1f5dfeab7fb892021576ab45205d4578acf5 (diff)
Bars example documented
Change-Id: Iac5fcb0cf1c822b09dbbe2c33f157d8b78b6bb75 Reviewed-by: Miikka Heikkinen <miikka.heikkinen@digia.com>
Diffstat (limited to 'examples')
-rw-r--r--examples/bars/doc/images/bars-example-2.pngbin0 -> 198263 bytes
-rw-r--r--examples/bars/doc/images/bars-example.pngbin163146 -> 135559 bytes
-rw-r--r--examples/bars/doc/src/bars.qdoc156
-rw-r--r--examples/bars/main.cpp73
4 files changed, 206 insertions, 23 deletions
diff --git a/examples/bars/doc/images/bars-example-2.png b/examples/bars/doc/images/bars-example-2.png
new file mode 100644
index 00000000..2083a8e0
--- /dev/null
+++ b/examples/bars/doc/images/bars-example-2.png
Binary files differ
diff --git a/examples/bars/doc/images/bars-example.png b/examples/bars/doc/images/bars-example.png
index 0f321c95..a87f4bdf 100644
--- a/examples/bars/doc/images/bars-example.png
+++ b/examples/bars/doc/images/bars-example.png
Binary files differ
diff --git a/examples/bars/doc/src/bars.qdoc b/examples/bars/doc/src/bars.qdoc
index 1db72e47..a8de709b 100644
--- a/examples/bars/doc/src/bars.qdoc
+++ b/examples/bars/doc/src/bars.qdoc
@@ -22,9 +22,161 @@
\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.
+ 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
- TODO
+ \section1 Example contents
*/
diff --git a/examples/bars/main.cpp b/examples/bars/main.cpp
index 861f1a58..e3ec17c5 100644
--- a/examples/bars/main.cpp
+++ b/examples/bars/main.cpp
@@ -71,14 +71,17 @@ GraphDataGenerator::GraphDataGenerator(Q3DBars *bargraph, QTableWidget *tableWid
m_rowCount(50),
m_tableWidget(tableWidget)
{
+ //! [5]
// Set up bar specifications; make the bars as wide as they are deep,
- // and add a small space between the bars
+ // and add a small space between them
m_graph->setBarThickness(1.0);
m_graph->setBarSpacing(QSizeF(0.2, 0.2));
// Set bar type to flat pyramids
m_graph->setBarType(QDataVis::MeshStylePyramids, false);
+ //! [5]
+
#ifndef USE_STATIC_DATA
// Set up sample space; make it as deep as it's wide
m_graph->setDataWindow(m_rowCount, m_columnCount);
@@ -93,16 +96,25 @@ GraphDataGenerator::GraphDataGenerator(Q3DBars *bargraph, QTableWidget *tableWid
m_graph->activeDataProxy()->setItemLabelFormat(QStringLiteral("@valueLabel"));
#else
- // Set selection mode to zoom row
+ //! [6]
+
+ // Set selection mode to slice row
m_graph->setSelectionMode(QDataVis::SelectionModeSliceRow);
+
+ // Set font
m_graph->setFont(QFont("Impact", 20));
+
+ //! [6]
#endif
+ //! [7]
+
// Set theme
m_graph->setTheme(QDataVis::ThemeDigia);
// Set preset camera position
m_graph->setCameraPreset(QDataVis::CameraPresetFront);
+ //! [7]
}
GraphDataGenerator::~GraphDataGenerator()
@@ -123,6 +135,7 @@ void GraphDataGenerator::start()
m_dataTimer->start(0);
m_tableWidget->setFixedWidth(m_graph->width());
#else
+ //! [8]
setupModel();
// Table needs to be shown before the size of its headers can be accurately obtained,
// so we postpone it a bit
@@ -130,11 +143,13 @@ void GraphDataGenerator::start()
m_dataTimer->setSingleShot(true);
QObject::connect(m_dataTimer, &QTimer::timeout, this, &GraphDataGenerator::fixTableSize);
m_dataTimer->start(0);
+ //! [8]
#endif
}
void GraphDataGenerator::setupModel()
{
+ //! [9]
// Set up row and column names
QStringList days;
days << "Monday" << "Tuesday" << "Wednesday" << "Thursday" << "Friday" << "Saturday" << "Sunday";
@@ -142,19 +157,23 @@ void GraphDataGenerator::setupModel()
weeks << "week 1" << "week 2" << "week 3" << "week 4" << "week 5";
// Set up data Mon Tue Wed Thu Fri Sat Sun
- float hours[5][7] = {{2.0f, 1.0f, 3.0f, 0.2f, 1.0f, 5.0f, 10.0f}, // week 1
- {0.5f, 1.0f, 3.0f, 1.0f, 2.0f, 2.0f, 3.0f}, // week 2
- {1.0f, 1.0f, 2.0f, 1.0f, 4.0f, 4.0f, 4.0f}, // week 3
- {0.0f, 1.0f, 0.0f, 0.0f, 2.0f, 2.0f, 0.3f}, // week 4
- {3.0f, 3.0f, 6.0f, 2.0f, 2.0f, 1.0f, 1.0f}}; // week 5
+ float hours[5][7] = {{2.0, 1.0, 3.0, 0.2, 1.0, 5.0, 10.0}, // week 1
+ {0.5, 1.0, 3.0, 1.0, 2.0, 2.0, 3.0}, // week 2
+ {1.0, 1.0, 2.0, 1.0, 4.0, 4.0, 4.0}, // week 3
+ {0.0, 1.0, 0.0, 0.0, 2.0, 2.0, 0.3}, // week 4
+ {3.0, 3.0, 6.0, 2.0, 2.0, 1.0, 1.0}}; // week 5
+ //! [9]
// Add labels
+ //! [10]
m_graph->rowAxis()->setTitle("Week of year");
m_graph->columnAxis()->setTitle("Day of week");
m_graph->valueAxis()->setTitle("Hours spent on the Internet");
m_graph->valueAxis()->setSegmentCount(5);
m_graph->valueAxis()->setLabelFormat("%.1f h");
+ //! [10]
+ //! [11]
m_tableWidget->setRowCount(5);
m_tableWidget->setColumnCount(7);
m_tableWidget->setHorizontalHeaderLabels(days);
@@ -162,13 +181,16 @@ void GraphDataGenerator::setupModel()
m_tableWidget->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
m_tableWidget->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
m_tableWidget->setCurrentCell(-1, -1);
+ //! [11]
+ //! [12]
for (int week = 0; week < weeks.size(); week++) {
for (int day = 0; day < days.size(); day++) {
QModelIndex index = m_tableWidget->model()->index(week, day);
m_tableWidget->model()->setData(index, hours[week][day]);
}
}
+ //! [12]
}
void GraphDataGenerator::addRow()
@@ -184,12 +206,15 @@ void GraphDataGenerator::addRow()
m_tableWidget->resizeColumnsToContents();
}
+//! [13]
void GraphDataGenerator::selectFromTable(const QPoint &selection)
{
m_tableWidget->setFocus();
m_tableWidget->setCurrentCell(selection.x(), selection.y());
}
+//! [13]
+//! [14]
void GraphDataGenerator::selectedFromTable(int currentRow, int currentColumn,
int previousRow, int previousColumn)
{
@@ -197,6 +222,7 @@ void GraphDataGenerator::selectedFromTable(int currentRow, int currentColumn,
Q_UNUSED(previousColumn)
m_graph->setSelectedBarPos(QPoint(currentRow, currentColumn));
}
+//! [14]
void GraphDataGenerator::fixTableSize()
{
@@ -210,45 +236,50 @@ void GraphDataGenerator::fixTableSize()
int main(int argc, char **argv)
{
+ //! [0]
QApplication app(argc, argv);
-
- QWidget widget;
- QVBoxLayout *layout = new QVBoxLayout(&widget);
-
Q3DBars *graph = new Q3DBars();
- QSize screenSize = graph->screen()->size();
-
QWidget *container = QWidget::createWindowContainer(graph);
+ //! [0]
+
+ QSize screenSize = graph->screen()->size();
container->setMinimumSize(QSize(screenSize.width() / 2, screenSize.height() / 2));
container->setMaximumSize(screenSize);
container->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
container->setFocusPolicy(Qt::StrongFocus);
- widget.setWindowTitle(QStringLiteral("Hours spent on the Internet"));
-
+ //! [1]
+ QWidget widget;
+ QVBoxLayout *layout = new QVBoxLayout(&widget);
QTableWidget *tableWidget = new QTableWidget(&widget);
- tableWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
- tableWidget->setAlternatingRowColors(true);
-
layout->addWidget(container, 1);
layout->addWidget(tableWidget, 1, Qt::AlignHCenter);
+ //! [1]
+ tableWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
+ tableWidget->setAlternatingRowColors(true);
+ widget.setWindowTitle(QStringLiteral("Hours spent on the Internet"));
+
+ //! [2]
// Since we are dealing with QTableWidget, the model will already have data sorted properly
- // in rows and columns, so create a custom mapping to utilize this.
+ // in rows and columns, so create a mapping to utilize this.
QItemModelBarDataMapping *mapping = new QItemModelBarDataMapping;
mapping->setUseModelCategories(true);
QItemModelBarDataProxy *proxy = new QItemModelBarDataProxy(tableWidget->model(), mapping);
graph->setActiveDataProxy(proxy);
+ //! [2]
+ //! [3]
GraphDataGenerator generator(graph, tableWidget);
-
QObject::connect(graph, &Q3DBars::selectedBarPosChanged, &generator,
&GraphDataGenerator::selectFromTable);
QObject::connect(tableWidget, &QTableWidget::currentCellChanged, &generator,
&GraphDataGenerator::selectedFromTable);
+ //! [3]
+ //! [4]
widget.show();
generator.start();
-
return app.exec();
+ //! [4]
}