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
|
/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the documentation of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:FDL$
** GNU Free Documentation License
** 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.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms
** and conditions contained in a signed written agreement between you
** and Nokia.
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
/*!
\example itemviews/frozencolumn
\title Frozen Column Example
This example demonstrates how to freeze a column within a QTableView.
\image frozencolumn-example.png "Screenshot of the example"
We use Qt's model/view framework to implement a table with its first
column frozen. This technique can be aplied to several columns or rows,
as long as they are on the edge of the table.
The model/view framework allows for one model to be displayed in different
ways using multiple views. For this example, we use two views on the same
model - two \l {QTableView}{table views} sharing one model. The frozen
column is a child of the main tableview, and we provide the desired visual
effect using an overlay technique which will be described step by step in
the coming sections.
\image frozencolumn-tableview.png
\section1 FreezeTableWidget Class Definition
The \c FreezeTableWidget class has a constructor and a destructor. Also, it
has two private members: the table view that we will use as an overlay, and
the shared model for both table views. Two slots are added to help keep the
section sizes in sync, as well as a function to readjust the frozen
column's geometry. In addition, we reimplement two functions:
\l{QAbstractItemView::}{resizeEvent()} and \l{QTableView::}{moveCursor()}.
\snippet examples/itemviews/frozencolumn/freezetablewidget.h Widget definition
\note QAbstractItemView is \l{QTableView}'s ancestor.
\section1 FreezeTableWidget Class Implementation
The constructor takes \a model as an argument and creates a table view that
we will use to display the frozen column. Then, within the constructor, we
invoke the \c init() function to set up the frozen column. Finally, we
connect the \l{QHeaderView::sectionResized()} signals (for horizontal and
vertical headers) to the appropriate slots. This ensures that our frozen
column's sections are in sync with the headers. We also connect the
vertical scrollbars together so that the frozen column scrolls vertically
with the rest of our table.
\snippet examples/itemviews/frozencolumn/freezetablewidget.cpp constructor
In the \c init() function, we ensure that the overlay table view
responsible for displaying the frozen column, is set up properly. This
means that this table view, \c frozenTableView, has to have the same model
as the main table view. However, the difference here is: \c frozenTableView's
only visible column is its first column; we hide the others using
\l{QTableView::}{setColumnHidden()}
\snippet examples/itemviews/frozencolumn/freezetablewidget.cpp init part1
In terms of the frozen column's z-order, we stack it on top of the
viewport. This is achieved by calling \l{QWidget::}{stackUnder()} on the
viewport. For appearance's sake, we prevent the column from stealing focus
from the main tableview. Also, we make sure that both views share the same
selection model, so only one cell can be selected at a time. A few other
tweaks are done to make our application look good and behave consistently
with the main tableview. Note that we called \c updateFrozenTableGeometry()
to make the column occupy the correct spot.
\snippet examples/itemviews/frozencolumn/freezetablewidget.cpp init part2
When you resize the frozen column, the same column on the main table view
must resize accordingly, to provide seamless integration. This is
accomplished by getting the new size of the column from the \c newSize
value from the \l{QHeaderView::}{sectionResized()} signal, emitted by both
the horizontal and vertical header.
\snippet examples/itemviews/frozencolumn/freezetablewidget.cpp sections
Since the width of the frozen column is modified, we adjust the geometry of
the widget accordingly by invoking \c updateFrozenTableGeometry(). This
function is further explained below.
In our reimplementation of QTableView::resizeEvent(), we call
\c updateFrozenTableGeometry() after invoking the base class
implementation.
\snippet examples/itemviews/frozencolumn/freezetablewidget.cpp resize
When navigating around the table with the keyboard, we need to ensure that
the current selection does not disappear behind the frozen column. To
synchronize this, we reimplement QTableView::moveCursor() and adjust the
scrollbar positions if needed, after calling the base class implementation.
\snippet examples/itemviews/frozencolumn/freezetablewidget.cpp navigate
The frozen column's geometry calculation is based on the geometry of the
table underneath, so it always appears in the right place. Using the
QFrame::frameWidth() function helps to calculate this geometry correctly,
no matter which style is used. We rely on the geometry of the viewport and
headers to set the boundaries for the frozen column.
\snippet examples/itemviews/frozencolumn/freezetablewidget.cpp geometry
*/
|