source: trunk/doc/html/customlayout.html@ 190

Last change on this file since 190 was 190, checked in by rudi, 14 years ago

reference documentation added

File size: 10.4 KB
Line 
1<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
2<!-- /home/espenr/tmp/qt-3.3.8-espenr-2499/qt-x11-free-3.3.8/doc/layout.doc:285 -->
3<html>
4<head>
5<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
6<title>Writing your own layout manager</title>
7<style type="text/css"><!--
8fn { margin-left: 1cm; text-indent: -1cm; }
9a:link { color: #004faf; text-decoration: none }
10a:visited { color: #672967; text-decoration: none }
11body { background: #ffffff; color: black; }
12--></style>
13</head>
14<body>
15
16<table border="0" cellpadding="0" cellspacing="0" width="100%">
17<tr bgcolor="#E5E5E5">
18<td valign=center>
19 <a href="index.html">
20<font color="#004faf">Home</font></a>
21 | <a href="classes.html">
22<font color="#004faf">All&nbsp;Classes</font></a>
23 | <a href="mainclasses.html">
24<font color="#004faf">Main&nbsp;Classes</font></a>
25 | <a href="annotated.html">
26<font color="#004faf">Annotated</font></a>
27 | <a href="groups.html">
28<font color="#004faf">Grouped&nbsp;Classes</font></a>
29 | <a href="functions.html">
30<font color="#004faf">Functions</font></a>
31</td>
32<td align="right" valign="center"><img src="logo32.png" align="right" width="64" height="32" border="0"></td></tr></table><h1 align=center>Writing your own layout manager</h1>
33
34
35<p> Here we present an example in detail. The class CardLayout is inspired
36by the Java layout manager of the same name. It lays out the items
37(widgets or nested layouts) on top of each other, each item offset by
38<a href="qlayout.html#spacing">QLayout::spacing</a>().
39<p> To write your own layout class, you must define the following:
40<ul>
41<li> A data structure to store the items handled by the layout. Each
42item is a <a href="qlayoutitem.html">QLayoutItem</a>. We will use a
43<a href="qptrlist.html">QPtrList</a> in this example.
44<li> <a href="qlayout.html#addItem">addItem()</a>, how to add items to
45the layout.
46<li> <a href="qlayout.html#setGeometry">setGeometry()</a>, how to perform
47the layout.
48<li> <a href="qlayoutitem.html#sizeHint">sizeHint()</a>, the preferred size
49of the layout.
50<li> <a href="qlayout.html#iterator">iterator()</a>, how to iterate over
51the layout.
52</ul>
53<p> In most cases, you will also implement <a href="qlayout.html#minimumSize">minimumSize</a>().
54<p> <h2> card.h
55</h2>
56<a name="1"></a><p> <pre>
57#ifndef CARD_H
58#define CARD_H
59
60#include &lt;<a href="qlayout-h.html">qlayout.h</a>&gt;
61#include &lt;<a href="qptrlist-h.html">qptrlist.h</a>&gt;
62
63class CardLayout : public <a href="qlayout.html">QLayout</a>
64{
65public:
66 CardLayout( <a href="qwidget.html">QWidget</a> *parent, int dist )
67 : <a href="qlayout.html">QLayout</a>( parent, 0, dist ) {}
68 CardLayout( <a href="qlayout.html">QLayout</a>* parent, int dist)
69 : <a href="qlayout.html">QLayout</a>( parent, dist ) { }
70 CardLayout( int dist )
71 : <a href="qlayout.html">QLayout</a>( dist ) {}
72 ~CardLayout();
73
74 void addItem(QLayoutItem *item);
75 <a href="qsize.html">QSize</a> sizeHint() const;
76 <a href="qsize.html">QSize</a> minimumSize() const;
77 <a href="qlayoutiterator.html">QLayoutIterator</a> iterator();
78 void setGeometry(const <a href="qrect.html">QRect</a> &amp;rect);
79
80private:
81 <a href="qptrlist.html">QPtrList</a>&lt;QLayoutItem&gt; list;
82};
83
84#endif
85</pre>
86
87<p> <h3> card.cpp
88</h3>
89<a name="1-1"></a><p> <pre>
90#include "card.h"
91</pre>
92
93<p> First we define an iterator over the layout. Layout iterators are used
94internally by the layout system to handle deletion of widgets. They
95are also available for application programmers.
96<p> There are two different classes involved: <a href="qlayoutiterator.html">QLayoutIterator</a> is the class
97that is visible to application programmers, it is <a href="shclass.html#explicitly-shared">explicitly shared</a>.
98The QLayoutIterator contains a <a href="qglayoutiterator.html">QGLayoutIterator</a> that does all the
99work. We must create a subclass of QGLayoutIterator that knows how to
100iterate over our layout class.
101<p> In this case, we choose a simple implementation: we store an integer
102index into the list and a pointer to the list. Every <a href="qglayoutiterator.html">QGLayoutIterator</a> subclass must implement <a href="qglayoutiterator.html#current">current</a>(), <a href="qglayoutiterator.html#next">next</a>() and <a href="qglayoutiterator.html#takeCurrent">takeCurrent</a>(), as well as a
103constructor. In our example we do not need a destructor.
104<p> <pre>
105class CardLayoutIterator : public <a href="qglayoutiterator.html">QGLayoutIterator</a>
106{
107public:
108 CardLayoutIterator( <a href="qptrlist.html">QPtrList</a>&lt;QLayoutItem&gt; *l )
109 : idx( 0 ), list( l ) {}
110
111 <a href="qlayoutitem.html">QLayoutItem</a> *current()
112 { return idx &lt; int(list-&gt;<a href="qptrlist.html#count">count</a>()) ? list-&gt;<a href="qptrlist.html#at">at</a>(idx) : 0; }
113
114 <a href="qlayoutitem.html">QLayoutItem</a> *next()
115 { idx++; return current(); }
116
117 <a href="qlayoutitem.html">QLayoutItem</a> *takeCurrent()
118 { return list-&gt;<a href="qptrlist.html#take">take</a>( idx ); }
119
120private:
121 int idx;
122 <a href="qptrlist.html">QPtrList</a>&lt;QLayoutItem&gt; *list;
123};
124</pre>
125
126<p> We must implement QLayout:iterator() to return a <a href="qlayoutiterator.html">QLayoutIterator</a> over
127this layout.
128<p> <pre>
129QLayoutIterator CardLayout::iterator()
130{
131 return QLayoutIterator( new CardLayoutIterator(&amp;list) );
132}
133</pre>
134
135<p> addItem() implements the default placement strategy for layout items.
136It must be implemented. It is used by <a href="qlayout.html#add">QLayout::add</a>(), by the <a href="qlayout.html">QLayout</a>
137constructor that takes a layout as parent, and it is used to implement
138the <a href="qlayout.html#autoAdd">auto-add</a> feature. If your layout
139has advanced placement options that require parameters, you must
140provide extra access functions such as <a href="qgridlayout.html#addMultiCell">QGridLayout::addMultiCell</a>().
141<p> <pre>
142void CardLayout::addItem( <a href="qlayoutitem.html">QLayoutItem</a> *item )
143{
144 list.append( item );
145}
146</pre>
147
148<p> The layout takes over responsibility of the items added. Since
149<a href="qlayoutitem.html">QLayoutItem</a> does not inherit <a href="qobject.html">QObject</a>, we must delete the items
150manually. The function <a href="qlayout.html#deleteAllItems">QLayout::deleteAllItems</a>() uses the iterator we
151defined above to delete all the items in the layout.
152<p> <pre>
153CardLayout::~CardLayout()
154{
155 deleteAllItems();
156}
157</pre>
158
159<p> The setGeometry() function actually performs the layout. The rectangle
160supplied as an argument does not include margin(). If relevant, use
161spacing() as the distance between items.
162<p> <pre>
163void CardLayout::setGeometry( const <a href="qrect.html">QRect</a> &amp;rect )
164{
165 QLayout::<a href="qlayout.html#setGeometry">setGeometry</a>( rect );
166
167 <a href="qptrlistiterator.html">QPtrListIterator</a>&lt;QLayoutItem&gt; it( list );
168 if (it.<a href="qptrlistiterator.html#count">count</a>() == 0)
169 return;
170
171 <a href="qlayoutitem.html">QLayoutItem</a> *item;
172
173 int i = 0;
174
175 int w = rect.<a href="qrect.html#width">width</a>() - ( list.count() - 1 ) * spacing();
176 int h = rect.<a href="qrect.html#height">height</a>() - ( list.count() - 1 ) * spacing();
177
178 while ( (item = it.<a href="qptrlistiterator.html#current">current</a>()) != 0 ) {
179 ++it;
180 <a href="qrect.html">QRect</a> geom( rect.<a href="qrect.html#x">x</a>() + i * spacing(), rect.<a href="qrect.html#y">y</a>() + i * spacing(),
181 w, h );
182 item-&gt;<a href="qlayoutitem.html#setGeometry">setGeometry</a>( geom );
183 ++i;
184 }
185}
186</pre>
187
188<p> sizeHint() and minimumSize() are normally very similar in
189implementation. The sizes returned by both functions should include
190spacing(), but not margin().
191<p> <pre>
192QSize CardLayout::sizeHint() const
193{
194 <a href="qsize.html">QSize</a> s( 0, 0 );
195 int n = list.count();
196 if ( n &gt; 0 )
197 s = QSize( 100, 70 ); // start with a nice default size
198 <a href="qptrlistiterator.html">QPtrListIterator</a>&lt;QLayoutItem&gt; it( list );
199 <a href="qlayoutitem.html">QLayoutItem</a> *item;
200 while ( (item = it.<a href="qptrlistiterator.html#current">current</a>()) != 0 ) {
201 ++it;
202 s = s.<a href="qsize.html#expandedTo">expandedTo</a>( item-&gt;<a href="qlayoutitem.html#minimumSize">minimumSize</a>() );
203 }
204 return s + n * QSize( spacing(), spacing() );
205}
206
207QSize CardLayout::minimumSize() const
208{
209 <a href="qsize.html">QSize</a> s( 0, 0 );
210 int n = list.count();
211 <a href="qptrlistiterator.html">QPtrListIterator</a>&lt;QLayoutItem&gt; it( list );
212 <a href="qlayoutitem.html">QLayoutItem</a> *item;
213 while ( (item = it.<a href="qptrlistiterator.html#current">current</a>()) != 0 ) {
214 ++it;
215 s = s.<a href="qsize.html#expandedTo">expandedTo</a>( item-&gt;<a href="qlayoutitem.html#minimumSize">minimumSize</a>() );
216 }
217 return s + n * QSize( spacing(), spacing() );
218}
219</pre>
220
221<p> <h2> Further Notes
222</h2>
223<a name="2"></a><p> This layout does not implement heightForWidth().
224<p> We ignore <a href="qlayoutitem.html#isEmpty">QLayoutItem::isEmpty</a>(), this means that the layout will
225treat hidden widgets as visible.
226<p> For complex layouts, speed can be greatly increased by caching
227calculated values. In that case, implement <a href="qlayoutitem.html#invalidate">QLayoutItem::invalidate</a>()
228to mark the cached data as dirty.
229<p> Calling <a href="qlayoutitem.html#sizeHint">QLayoutItem::sizeHint</a>(), etc. may be expensive, so you should
230store the value in a local variable if you need it again later in the
231same function.
232<p> You should not call <a href="qlayoutitem.html#setGeometry">QLayoutItem::setGeometry</a>() twice on the same item
233in the same function. That can be very expensive if the item has
234several child widgets, because it will have to do a complete layout
235every time. Instead, calculate the geometry and then set it. (This
236doesn't only apply to layouts, you should do the same if you implement
237your own resizeEvent().)
238<p>
239<!-- eof -->
240<p><address><hr><div align=center>
241<table width=100% cellspacing=0 border=0><tr>
242<td>Copyright &copy; 2007
243<a href="troll.html">Trolltech</a><td align=center><a href="trademarks.html">Trademarks</a>
244<td align=right><div align=right>Qt 3.3.8</div>
245</table></div></address></body>
246</html>
Note: See TracBrowser for help on using the repository browser.