Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
modelview.qdoc
Go to the documentation of this file.
1
// Copyright (C) 2016 The Qt Company Ltd.
2
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
3
4
/*!
5
\page modelview.html
6
\ingroup tutorials
7
\startpage {index.html}{Qt Reference Documentation}
8
9
\title Model/View Tutorial
10
\brief An introduction to ModelView programming
11
12
Every UI developer should know about ModelView programming and the goal of
13
this tutorial is to provide you with an easily understandable introduction
14
to this topic.
15
16
Table, list and tree widgets are components frequently used in GUIs. There
17
are 2 different ways how these widgets can access their data. The
18
traditional way involves widgets which include internal containers for
19
storing data. This approach is very intuitive, however, in many non-trivial
20
applications, it leads to data synchronization issues.
21
The second approach is model/view programming, in
22
which widgets do not maintain internal data containers. They access external
23
data through a standardized interface and therefore avoid data duplication.
24
This may seem complicated at first, but once you take a closer look, it is
25
not only easy to grasp, but the many benefits of model/view programming also
26
become clearer.
27
28
\image treeview.png {Directory and its contents in a tree view}
29
30
In the process, we will learn about some basic technologies provided by Qt,
31
such as:
32
33
\list
34
\li The difference between standard and model/view widgets
35
\li Adapters between forms and models
36
\li Developing a simple model/view application
37
\li Predefined models
38
\li Intermediate topics such as:
39
\list
40
\li Tree views
41
\li Selection
42
\li Delegates
43
\li Debugging with model test
44
\endlist
45
\endlist
46
47
You will also learn whether your new application can be written easier with
48
model/view programming or if classic widgets will work just as well.
49
50
This tutorial includes example code for you to edit and integrate into your
51
project. The tutorial's source code is located in Qt's
52
\e examples/widgets/tutorials/modelview directory.
53
54
For more detailed information you may also want to look at the
55
\l{model-view-programming.html}{reference documentation}
56
57
58
\section1 1. Introduction
59
60
Model/View is a technology used to separate data from views in widgets that
61
handle data sets. Standard widgets are not designed for separating data
62
from views and this is why Qt has two different types of widgets. Both
63
types of widgets look the same, but they interact with data differently.
64
65
\table
66
\row
67
\li Standard widgets use data that is part of the widget.
68
\li \image standardwidget.png
69
{Structure where the "view" is separate from the "data"}
70
\row
71
\li View classes operate on external data (the model)
72
\li \image modelview.png
73
{Structure that uses a "view" and a "model" for the data }
74
\endtable
75
76
\section2 1.1 Standard Widgets
77
78
Let's have a closer look at a standard table widget. A table widget is a 2D
79
array of the data elements that the user can change. The table widget can be
80
integrated into a program flow by reading and writing the data elements that
81
the table widget provides.
82
This method is very intuitive and useful in many applications, but displaying
83
and editing a database table with a standard table widget can be problematic.
84
Two copies of the data have to be coordinated: one outside the
85
widget; one inside the widget. The developer is responsible for
86
synchronizing both versions. Besides this, the tight coupling of presentation and data
87
makes it harder to write unit tests.
88
89
\section2 1.2 Model/View to the Rescue
90
91
Model/view stepped up to provide a solution that uses a more versatile
92
architecture. Model/view eliminates the data consistency problems that may
93
occur with standard widgets. Model/view also makes it easier to use more
94
than one view of the same data because one model can be passed on to many
95
views. The most important difference is that model/view widgets do not store
96
data behind the table cells. In fact, they operate directly from your data.
97
Since view classes do not know your data's structure, you need to provide a
98
wrapper to make your data conform to the QAbstractItemModel interface. A
99
view uses this interface to read from and write to your data. Any instance
100
of a class that implements QAbstractItemModel is said to be a model. Once
101
the view receives a pointer to a model, it will read and display its content
102
and be its editor.
103
104
\section2 1.3 Overview of the Model/View Widgets
105
106
Here is an overview of the model/view widgets and their corresponding
107
standard widgets.
108
109
\table
110
\header
111
\li Widget
112
\li Standard Widget\br
113
(an item based convenience class)
114
\li Model/View View Class\br
115
(for use with external data)
116
\row
117
\li \inlineimage listview.png
118
{Directory displaying its contents as a list}
119
\li \l QListWidget
120
\li \l QListView
121
\row
122
\li \inlineimage tableview.png
123
{Directory displaying its contents as a table}
124
\li \l QTableWidget
125
\li \l QTableView
126
\row
127
\li \inlineimage treeview.png
128
{Directory displaying its contents as a tree}
129
\li \l QTreeWidget
130
\li \l QTreeView
131
\row
132
\li \inlineimage columnview.png
133
{Directory displaying its contents as columns}
134
\li
135
\li \l QColumnView shows a tree as a hierarchy of lists
136
\row
137
\li \inlineimage modelview-combobox.png
138
{Combobox showing an entry in the model}
139
\li {2, 1} \l QComboBox can work as both a view class and also
140
as a traditional widget
141
\endtable
142
143
\section2 1.4 Using Adapters between Forms and Models
144
145
Having adapters between forms and models can come in handy.
146
147
We can edit data stored in tables directly from within the table itself, but
148
it's much more comfortable to edit data in text fields. There is no direct
149
model/view counterpart that separates data and views for widgets that
150
operate on one value (QLineEdit, QCheckBox ...) instead of a dataset, so we
151
need an adapter in order to connect the form to the source of data.
152
153
\l QDataWidgetMapper is a great solution because it maps form widgets to a
154
table row and makes it very easy to build forms for database tables.
155
156
\image widgetmapper.png {Form with personal and other information}
157
158
Another example of an adapter is \l QCompleter. Qt has \l QCompleter for
159
providing auto-completions in Qt widgets such as \l QComboBox and, as shown
160
below, \l QLineEdit. \l QCompleter uses a model as its data source.
161
162
\image qcompleter.png {Completer with suggestions for the characters "Em"}
163
164
165
\section1 2. A Simple Model/View Application
166
If you want to develop a model/view application, where should you start?
167
We recommend starting with a simple example and extending it step-by-step.
168
This makes understanding the architecture a lot easier. Trying to understand
169
the model/view architecture in detail before invoking the IDE has proven
170
to be less convenient for many developers. It is substantially easier to
171
start with a simple model/view application that has demo data. Give it a
172
try! Simply replace the data in the examples below with your own.
173
174
Below are 7 very simple and independent applications that show different
175
sides of model/view programming. The source code can be found inside the
176
\c{examples/widgets/tutorials/modelview} directory.
177
178
\section2 2.1 A Read Only Table
179
180
We start with an application that uses a QTableView to show data. We will
181
add editing capabilities later.
182
183
(file source: examples/widgets/tutorials/modelview/1_readonly/main.cpp)
184
\snippet tutorials/modelview/1_readonly/main.cpp Quoting ModelView Tutorial
185
186
We have the usual \l {modelview-part2-main-cpp.html}{main()} function:
187
188
Here is the interesting part: We create an instance of MyModel and use
189
\l{QTableView::setModel()}{tableView.setModel(&myModel);} to pass a
190
pointer of it to \l{QTableView}{tableView}. \l{QTableView}{tableView}
191
will invoke the methods of the pointer it has received to find out two
192
things:
193
194
\list
195
\li How many rows and columns should be displayed.
196
\li What content should be printed into each cell.
197
\endlist
198
199
The model needs some code to respond to this.
200
201
We have a table data set, so let's start with QAbstractTableModel since it
202
is easier to use than the more general QAbstractItemModel.
203
204
(file source: examples/widgets/tutorials/modelview/1_readonly/mymodel.h)
205
\snippet tutorials/modelview/1_readonly/mymodel.h Quoting ModelView Tutorial
206
207
QAbstractTableModel requires the implementation of three abstract methods.
208
209
(file source: examples/widgets/tutorials/modelview/1_readonly/mymodel.cpp)
210
\snippet tutorials/modelview/1_readonly/mymodel.cpp Quoting ModelView Tutorial
211
212
The number of rows and columns is provided by
213
\l{QAbstractItemModel::rowCount()}{MyModel::rowCount()} and
214
\l{QAbstractItemModel::columnCount()}{MyModel::columnCount()}. When the view
215
has to know what the cell's text is, it calls the method
216
\l{QAbstractItemModel::data()}{MyModel::data()}. Row and column information
217
is specified with parameter \c index and the role is set to
218
\l{Qt::ItemDataRole}{Qt::DisplayRole}. Other roles are covered in the next
219
section. In our example, the data that should be displayed is generated. In
220
a real application, \c MyModel would have a member called \c MyData, which
221
serves as the target for all reading and writing operations.
222
223
This small example demonstrates the passive nature of a model. The model
224
does not know when it will be used or which data is needed. It simply
225
provides data each time the view requests it.
226
227
What happens when the model's data needs to be changed? How does the view
228
realize that data has changed and needs to be read again? The model has to
229
emit a signal that indicates what range of cells has changed. This will be
230
demonstrated in section 2.3.
231
232
\section2 2.2 Extending the Read Only Example with Roles
233
234
In addition to controlling what text the view displays, the model also
235
controls the text's appearance. When we slightly change the model, we get
236
the following result:
237
238
\image readonlytable_role.png {Table with custom formatting applied to its cells}
239
240
In fact, nothing except for the \l{QAbstractItemModel::}{data()} method
241
needs to be changed to set fonts, background colour, alignment and a
242
checkbox.
243
Below is the \l{QAbstractItemModel::data()}{data()} method that produces the
244
result shown above. The difference is that this time we use parameter int
245
role to return different pieces of information depending on its value.
246
247
(file source: examples/widgets/tutorials/modelview/2_formatting/mymodel.cpp)
248
\snippet tutorials/modelview/2_formatting/mymodel.cpp Quoting ModelView Tutorial
249
250
Each formatting property will be requested from the model with a separate
251
call to the \l{QAbstractItemModel::data()}{data()} method. The \c role
252
parameter is used to let the model know which property is being requested:
253
254
\table
255
\header
256
\li \l{Qt::ItemDataRole}{enum Qt::ItemDataRole}
257
\li Meaning
258
\li Type
259
\row
260
\li \l{Qt::ItemDataRole}{}Qt::DisplayRole
261
\li text
262
\li QString
263
\row
264
\li \l{Qt::ItemDataRole}{Qt::FontRole}
265
\li font
266
\li QFont
267
\row
268
\li \l{Qt::ItemDataRole}{BackgroundRole}
269
\li brush for the background of the cell
270
\li QBrush
271
\row
272
\li \l{Qt::ItemDataRole}{Qt::TextAlignmentRole}
273
\li text alignment
274
\li \l{Qt::AlignmentFlag}{enum Qt::AlignmentFlag}
275
\row
276
\li {1, 3} \l{Qt::ItemDataRole}{Qt::CheckStateRole}
277
\li {1, 3} suppresses checkboxes with \l{QVariant}{QVariant()},
278
279
sets checkboxes with \l{Qt::CheckState}{Qt::Checked}
280
281
or \l{Qt::CheckState}{Qt::Unchecked}
282
\li {1, 3} \l{Qt::ItemDataRole}{enum Qt::ItemDataRole}
283
\endtable
284
285
Refer to the Qt namespace documentation to learn more about the
286
\l{Qt::ItemDataRole}{Qt::ItemDataRole} enum's capabilities.
287
288
Now we need to determine how using a separated model impacts the
289
application's performance, so let's trace how often the view calls the
290
\l{QAbstractItemModel::}{data()} method. In order to track how often the
291
view calls the model, we have put a debug statement in the
292
\l{QAbstractItemModel::}{data()} method, which logs onto the error output
293
stream. In our small example, \l{QAbstractItemModel::}{data()} will be
294
called 42 times.
295
Each time you hover the cursor over the field,
296
\l{QAbstractItemModel::}{data()} will be called again -- 7 times for
297
each cell. That's why it is important to make sure that your data is
298
available when \l{QAbstractItemModel::}{data()} is invoked and expensive
299
lookup operations are cached.
300
301
\section2 2.3 A Clock inside a Table Cell
302
303
\image clock.png {Table that displays the time in a cell}
304
305
We still have a read only table, but this time the content changes every
306
second because we are showing the current time.
307
308
(file source: examples/widgets/tutorials/modelview/3_changingmodel/mymodel.cpp)
309
\snippet tutorials/modelview/3_changingmodel/mymodel.cpp quoting mymodel_QVariant
310
311
Something is missing to make the clock tick. We need to tell the view every
312
second that the time has changed and that it needs to be read again. We do
313
this with a timer. In the constructor, we set its interval to 1 second and
314
connect its timeout signal.
315
316
(file source: examples/widgets/tutorials/modelview/3_changingmodel/mymodel.cpp)
317
\snippet tutorials/modelview/3_changingmodel/mymodel.cpp quoting mymodel_a
318
319
Here is the corresponding slot:
320
321
(file source: examples/widgets/tutorials/modelview/3_changingmodel/mymodel.cpp)
322
\snippet tutorials/modelview/3_changingmodel/mymodel.cpp quoting mymodel_b
323
324
We ask the view to read the data in the top left cell again by emitting the
325
\l{QAbstractItemModel::}{dataChanged()} signal. Note that we did not
326
explicitly connect the \l{QAbstractItemModel::}{dataChanged()} signal to the
327
view. This happened automatically when we called \l{QTableView::}{setModel()}.
328
329
\section2 2.4 Setting up Headers for Columns and Rows
330
331
Headers can be hidden via a view method: \c{tableView->verticalHeader()->hide();}
332
\image modelview-header.png {Table showing the column headers}
333
334
The header content, however, is set via the model, so we reimplement the
335
\l{QAbstractItemModel::headerData()}{headerData()} method:
336
337
(file source: examples/widgets/tutorials/modelview/4_headers/mymodel.cpp)
338
\snippet tutorials/modelview/4_headers/mymodel.cpp quoting mymodel_c
339
340
Note that method \l{QAbstractItemModel::headerData()}{headerData()} also has
341
a parameter role which has the same meaning as in
342
\l{QAbstractItemModel::data()}{MyModel::data()}.
343
344
\section2 2.5 The Minimal Editing Example
345
346
In this example, we are going to build an application that automatically
347
populates a window title with content by repeating values entered into table
348
cells. To be able to access the window title easily we put the QTableView in
349
a QMainWindow.
350
351
The model decides whether editing capabilities are available. We only have
352
to modify the model in order for the available editing capabilities to be
353
enabled. This is done by reimplementing the following virtual methods:
354
\l{QAbstractItemModel::}{setData()} and \l{QAbstractItemModel::}{flags()}.
355
356
(file source: examples/widgets/tutorials/modelview/5_edit/mymodel.h)
357
\snippet tutorials/modelview/5_edit/mymodel.h Quoting ModelView Tutorial
358
359
We use \c the two-dimensional array QString \c m_gridData to store our data.
360
This makes \c m_gridData the core of \c MyModel. The rest of \c MyModel acts
361
like a wrapper and adapts \c m_gridData to the QAbstractItemModel
362
interface. We have also introduced the \c editCompleted() signal, which
363
makes it possible to transfer the modified text to the window title.
364
365
(file source: examples/widgets/tutorials/modelview/5_edit/mymodel.cpp)
366
\snippet tutorials/modelview/5_edit/mymodel.cpp quoting mymodel_e
367
368
\l{QAbstractItemModel::setData()}{setData()} will be called each time the
369
user edits a cell. The \c index parameter tells us which field has been
370
edited and \c value provides the result of the editing process. The role
371
will always be set to \l Qt::EditRole because our cells only contain text.
372
If a checkbox were present and user permissions are set to allow the
373
checkbox to be selected, calls would also be made with the role set to
374
\l Qt::CheckStateRole.
375
376
(file source: examples/widgets/tutorials/modelview/5_edit/mymodel.cpp)
377
\snippet tutorials/modelview/5_edit/mymodel.cpp quoting mymodel_f
378
379
Various properties of a cell can be adjusted with
380
\l{QAbstractItemModel::flags()}{flags()}.
381
382
Returning \l{Qt::ItemFlag}{Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled}
383
is enough to show an editor that a cell can be selected.
384
385
If editing one cell modifies more data than the data in that particular
386
cell, the model must emit a \l{QAbstractItemModel::}{dataChanged()} signal
387
in order for the data that has been changed to be read.
388
389
390
\section1 3. Intermediate Topics
391
392
\section2 3.1 TreeView
393
394
You can convert the example above into an application with a tree view.
395
Simply replace QTableView with QTreeView, which results in a read/write
396
tree. No changes have to be made to the model. The tree won't have any
397
hierarchies because there aren't any hierarchies in the model itself.
398
399
\image dummy_tree.png {Tree view displaying table data with no hierarchy}
400
401
QListView, QTableView and QTreeView all use a model abstraction, which is a
402
merged list, table and tree. This makes it possible to use several different
403
types of view classes from the same model.
404
405
\image list_table_tree.png
406
{Diagram comparing list model, table model, and tree model}
407
408
This is how our example model looks so far:
409
410
\image example_model.png {Diagram of current model structure}
411
412
We want to present a real tree. We have wrapped our data in the examples
413
above in order to make a model. This time we use QStandardItemModel, which
414
is a container for hierarchical data that also implements
415
QAbstractItemModel. To show a tree, QStandardItemModel must be populated
416
with \l{QStandardItem}s, which are able to hold all the standard properties
417
of items like text, fonts, checkboxes or brushes.
418
419
\image tree_2_with_algorithm.png {Diagram of the model and the view}
420
421
(file source: examples/widgets/tutorials/modelview/6_treeview/mainwindow.cpp)
422
\snippet tutorials/modelview/6_treeview/mainwindow.cpp Quoting ModelView Tutorial
423
424
We simply instantiate a QStandardItemModel and add a couple of
425
\l{QStandardItem}{QStandardItems} to the constructor. We can then make a
426
hierarchical data structure because a QStandardItem can hold other
427
\l{QStandardItem}{QStandardItems}. Nodes are collapsed and expanded within
428
the view.
429
430
\section2 3.2 Working with Selections
431
432
We want to access a selected item's content in order to output it into the
433
window title together with the hierarchy level.
434
435
\image selection2.png {View of a model with the selected content in blue}
436
437
So let's create a couple of items:
438
439
(file source: examples/widgets/tutorials/modelview/7_selections/mainwindow.cpp)
440
\snippet tutorials/modelview/7_selections/mainwindow.cpp quoting modelview_a
441
442
Views manage selections within a separate selection model, which can be
443
retrieved with the \l{QAbstractItemView::}{selectionModel()} method. We
444
retrieve the selection Model in order to connect a slot to its
445
\l{QAbstractItemView::}{selectionChanged()} signal.
446
447
(file source: examples/widgets/tutorials/modelview/7_selections/mainwindow.cpp)
448
\snippet tutorials/modelview/7_selections/mainwindow.cpp quoting modelview_b
449
450
We get the model index that corresponds to the selection by calling
451
\l{QItemSelectionModel::currentIndex()}{treeView->selectionModel()->currentIndex()}
452
and we get the field's string by using the model index. Then we just
453
calculate the item's \c hierarchyLevel. Top level items do not have parents
454
and the \l{QAbstractItemModel::}{parent()} method will return a default
455
constructed \l{QModelIndex}{QModelIndex()}. This is why we use the
456
\l{QAbstractItemModel::}{parent()} method to iterate to the top level while
457
counting the steps performed during iteration.
458
459
The selection model (as shown above) can be retrieved, but it can also be
460
set with \l{QAbstractItemView}{QAbstractItemView::setSelectionModel}. This
461
is how it's possible to have 3 view classes with synchronized selections
462
because only one instance of a selection model is used. To share a selection
463
model between 3 views use \l{QAbstractItemView::}{selectionModel()} and
464
assign the result to the second and third view class with
465
\l{QAbstractItemView::}{setSelectionModel()}.
466
467
\section2 3.3 Predefined Models
468
469
The typical way to use model/view is to wrap specific data to make it usable
470
with view classes. Qt, however, also provides predefined models for common
471
underlying data structures. If one of the available data structures is
472
suitable for your application, a predefined model can be a good choice.
473
474
\table
475
\row
476
\li QStringListModel
477
\li Stores a list of strings
478
\row
479
\li QStandardItemModel
480
\li Stores arbitrary hierarchical items
481
\row
482
\li QFileSystemModel
483
\li Encapsulate the local file system
484
\row
485
\li QSqlQueryModel
486
\li Encapsulate an SQL result set
487
\row
488
\li QSqlTableModel
489
\li Encapsulates an SQL table
490
\row
491
\li QSqlRelationalTableModel
492
\li Encapsulates an SQL table with foreign keys
493
\row
494
\li QSortFilterProxyModel
495
\li Sorts and/or filters another model
496
497
\endtable
498
499
\section2 3.4 Delegates
500
501
In all examples so far, data is presented as text or a checkbox in a cell
502
and is edited as text or a checkbox. The component that provides these
503
presentation and editing services is called a \e delegate. We are only just
504
beginning to work with the delegate because the view uses a default
505
delegate. But imagine that we want to have a different editor (e.g., a
506
slider or a drop down list) Or imagine that we want to present data as
507
graphics.
508
Let's take a look at an example called \l{Star Delegate Example}{Star
509
Delegate}, in which stars are used to show a rating:
510
511
\image stardelegate.png {Table showing songs and their star ratings}
512
513
The view has a \l{QAbstractItemView::}{setItemDelegate()} method that
514
replaces the default delegate and installs a custom delegate.
515
A new delegate can be written by creating a class that inherits from
516
QStyledItemDelegate. In order to write a delegate that displays stars and
517
has no input capabilities, we only need to override 2 methods.
518
519
\code
520
class StarDelegate : public QStyledItemDelegate
521
{
522
Q_OBJECT
523
public:
524
StarDelegate(QWidget *parent = nullptr);
525
void paint(QPainter *painter, const QStyleOptionViewItem &option,
526
const QModelIndex &index) const;
527
QSize sizeHint(const QStyleOptionViewItem &option,
528
const QModelIndex &index) const;
529
};
530
\endcode
531
532
\l{QStyledItemDelegate::}{paint()} draws stars depending on the content of
533
the underlying data. The data can be looked up by calling
534
\l{QModelIndex::data()}{index.data()}. The delegate's
535
\l{QAbstractItemDelegate::}{sizeHint()} method is used to obtain each
536
star's dimensions, so the cell will provide enough height and width to
537
accommodate the stars.
538
539
Writing custom delegates is the right choice if you want to show your data
540
with a custom graphical representation inside the grid of the view class. If
541
you want to leave the grid, you would not use a custom delegate but a custom
542
view class.
543
544
Other references to delegates in Qt Documentation:
545
546
\list
547
\li \l{Delegate Classes}
548
\li \l{QAbstractItemDelegate}{QAbstractItemDelegate Class Reference}
549
\li \l{QSqlRelationalDelegate}{QSqlRelationalDelegate Class Reference}
550
\li \l{QStyledItemDelegate}{QStyledItemDelegate Class Reference}
551
\li \l{QItemDelegate}{QItemDelegate Class Reference}
552
\endlist
553
554
555
\section2 3.5 Debugging with ModelTest
556
557
The passive nature of models provides new challenges for programmers.
558
Inconsistencies in the model can cause the application to crash. Since the
559
model is hit by numerous calls from the view, it is hard to find out which
560
call has crashed the application and which operation has introduced the
561
problem.
562
563
Qt Labs provides software called
564
\l{http://wiki.qt.io/Model_Test}{ModelTest},
565
which checks models while your programming is running. Every time the model
566
is changed, ModelTest scans the model and reports errors with an assert.
567
This is especially important for tree models, since their hierarchical
568
nature leaves many possibilities for subtle inconsistencies.
569
570
Unlike view classes, ModelTest uses out of range indexes to test the model.
571
This means your application may crash with ModelTest even if it runs
572
perfectly without it. So you also need to handle all of the indexes that are
573
out of range when using ModelTest.
574
575
576
\section1 Examples
577
578
Qt comes with multiple examples for model/view. You can find them on the
579
\l{Item Views Examples} page.
580
*/
581
582
/*!
583
\page modelview-part2-main-cpp.html
584
\title main.cpp
585
\quotefile tutorials/modelview/1_readonly/main.cpp
586
*/
qtbase
src
widgets
doc
src
modelview.qdoc
Generated on
for Qt by
1.14.0