[190] | 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/coordsys.doc:36 -->
|
---|
| 3 | <html>
|
---|
| 4 | <head>
|
---|
| 5 | <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
---|
| 6 | <title>The Coordinate System</title>
|
---|
| 7 | <style type="text/css"><!--
|
---|
| 8 | fn { margin-left: 1cm; text-indent: -1cm; }
|
---|
| 9 | a:link { color: #004faf; text-decoration: none }
|
---|
| 10 | a:visited { color: #672967; text-decoration: none }
|
---|
| 11 | body { 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 Classes</font></a>
|
---|
| 23 | | <a href="mainclasses.html">
|
---|
| 24 | <font color="#004faf">Main 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 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>The Coordinate System</h1>
|
---|
| 33 |
|
---|
| 34 |
|
---|
| 35 |
|
---|
| 36 | <p> A <a href="qpaintdevice.html">paint device</a> in Qt is a drawable 2D
|
---|
| 37 | surface. <a href="qwidget.html">QWidget</a>, <a href="qpixmap.html">QPixmap</a>, <a href="qpicture.html">QPicture</a> and <a href="qprinter.html">QPrinter</a> are all
|
---|
| 38 | paint devices. A <a href="qpainter.html">QPainter</a> is an object which can draw on such
|
---|
| 39 | devices.
|
---|
| 40 | <p> The default coordinate system of a paint device has its origin at the
|
---|
| 41 | top left corner. X increases to the right and Y increases downwards.
|
---|
| 42 | The unit is one pixel on pixel-based devices and one point on
|
---|
| 43 | printers.
|
---|
| 44 | <p> <h2> An Example
|
---|
| 45 | </h2>
|
---|
| 46 | <a name="1"></a><p> The illustration below shows a highly magnified portion of the top
|
---|
| 47 | left corner of a paint device.
|
---|
| 48 | <p> <center><img src="coordsys.png"></center>
|
---|
| 49 | <p> The rectangle and the line were drawn by this code (with the grid
|
---|
| 50 | added and colors touched up in the illustration):
|
---|
| 51 | <p> <pre>
|
---|
| 52 | void MyWidget::paintEvent( <a href="qpaintevent.html">QPaintEvent</a> * )
|
---|
| 53 | {
|
---|
| 54 | <a href="qpainter.html">QPainter</a> p( this );
|
---|
| 55 | p.<a href="qpainter.html#setPen">setPen</a>( darkGray );
|
---|
| 56 | p.<a href="qpainter.html#drawRect">drawRect</a>( 1,2, 5,4 );
|
---|
| 57 | p.<a href="qpainter.html#setPen">setPen</a>( lightGray );
|
---|
| 58 | p.<a href="qpainter.html#drawLine">drawLine</a>( 9,2, 7,7 );
|
---|
| 59 | }
|
---|
| 60 | </pre>
|
---|
| 61 |
|
---|
| 62 | <p> Note that all of the pixels drawn by drawRect() are inside the size
|
---|
| 63 | specified (5*4 pixels). This is different from some toolkits; in Qt
|
---|
| 64 | the size you specify exactly encompasses the pixels drawn. This
|
---|
| 65 | applies to all the relevant functions in <a href="qpainter.html">QPainter</a>.
|
---|
| 66 | <p> Similarly, the drawLine() call draws both endpoints of the line, not
|
---|
| 67 | just one.
|
---|
| 68 | <p> Here are the classes that relate most closely to the coordinate
|
---|
| 69 | system:
|
---|
| 70 | <p> <center><table cellpadding="4" cellspacing="2" border="0">
|
---|
| 71 | <tr bgcolor="#f0f0f0"> <td valign="top"><a href="qpoint.html">QPoint</a>
|
---|
| 72 | <td valign="top">A single 2D point in the coordinate system. Most functions in
|
---|
| 73 | Qt that deal with points can accept either a <a href="qpoint.html">QPoint</a> argument
|
---|
| 74 | or two ints, for example <a href="qpainter.html#drawPoint">QPainter::drawPoint</a>().
|
---|
| 75 | <tr bgcolor="#d0d0d0"> <td valign="top"><a href="qsize.html">QSize</a>
|
---|
| 76 | <td valign="top">A single 2D vector. Internally, QPoint and <a href="qsize.html">QSize</a> are the same,
|
---|
| 77 | but a point is not the same as a size, so both classes exist.
|
---|
| 78 | Again, most functions accept either a QSize or two ints, for
|
---|
| 79 | example <a href="qwidget.html#resize">QWidget::resize</a>().
|
---|
| 80 | <tr bgcolor="#f0f0f0"> <td valign="top"><a href="qrect.html">QRect</a>
|
---|
| 81 | <td valign="top">A 2D rectangle. Most functions accept either a <a href="qrect.html">QRect</a> or four
|
---|
| 82 | ints, for example <a href="qwidget.html#setGeometry">QWidget::setGeometry</a>().
|
---|
| 83 | <tr bgcolor="#d0d0d0"> <td valign="top"><a href="qregion.html">QRegion</a>
|
---|
| 84 | <td valign="top">An arbitrary set of points, including all the normal set
|
---|
| 85 | operations, e.g. <a href="qregion.html#intersect">QRegion::intersect</a>(), and also a less
|
---|
| 86 | usual function to return a list of rectangles whose union is
|
---|
| 87 | equal to the region. <a href="qregion.html">QRegion</a> is used e.g. by <a href="qpainter.html#setClipRegion">QPainter::setClipRegion</a>(), <a href="qwidget.html#repaint">QWidget::repaint</a>() and <a href="qpaintevent.html#region">QPaintEvent::region</a>().
|
---|
| 88 | <tr bgcolor="#f0f0f0"> <td valign="top"><a href="qpainter.html">QPainter</a>
|
---|
| 89 | <td valign="top">The class that paints. It can paint on any device with the
|
---|
| 90 | same code. There are differences between devices, <a href="qprinter.html#newPage">QPrinter::newPage</a>() is a good example, but <a href="qpainter.html">QPainter</a> works the
|
---|
| 91 | same way on all devices.
|
---|
| 92 | <tr bgcolor="#d0d0d0"> <td valign="top"><a href="qpaintdevice.html">QPaintDevice</a>
|
---|
| 93 | <td valign="top">A device on which QPainter can paint. There are two internal
|
---|
| 94 | devices, both pixel-based, and two external devices, <a href="qprinter.html">QPrinter</a> and <a href="qpicture.html">QPicture</a> (which records QPainter commands to a
|
---|
| 95 | file or other <a href="qiodevice.html">QIODevice</a>, and plays them back). Other
|
---|
| 96 | devices can be defined.
|
---|
| 97 | </table></center>
|
---|
| 98 | <p> <h2> Transformations
|
---|
| 99 | </h2>
|
---|
| 100 | <a name="2"></a><p> Although Qt's default coordinate system works as described above, <a href="qpainter.html">QPainter</a> also supports arbitrary transformations.
|
---|
| 101 | <p> This transformation engine is a three-step pipeline, closely following
|
---|
| 102 | the model outlined in books such as
|
---|
| 103 | <a href="http://www.amazon.com/exec/obidos/ASIN/0201848406/trolltech/t">Foley & Van Dam</a> and the
|
---|
| 104 | <a href="http://www.amazon.com/exec/obidos/ASIN/0201604582/trolltech/t">OpenGL Programming Guide.</a> Refer to those for in-depth
|
---|
| 105 | coverage; here we give just a brief overview and an example.
|
---|
| 106 | <p> The first step uses the world <a href="qwmatrix.html#TransformationMode">transformation matrix</a>. Use this matrix
|
---|
| 107 | to orient and position your objects in your model. Qt provides
|
---|
| 108 | methods such as <a href="qpainter.html#rotate">QPainter::rotate</a>(), <a href="qpainter.html#scale">QPainter::scale</a>(), <a href="qpainter.html#translate">QPainter::translate</a>() and so on to operate on this matrix.
|
---|
| 109 | <p> <a href="qpainter.html#save">QPainter::save</a>() and <a href="qpainter.html#restore">QPainter::restore</a>() save and restore this
|
---|
| 110 | matrix. You can also use <a href="qwmatrix.html">QWMatrix</a> objects, <a href="qpainter.html#worldMatrix">QPainter::worldMatrix</a>() and <a href="qpainter.html#setWorldMatrix">QPainter::setWorldMatrix</a>() to store and
|
---|
| 111 | use named matrices.
|
---|
| 112 | <p> The second step uses the window. The window describes the view
|
---|
| 113 | boundaries in model coordinates. The matrix positions the <em>objects</em>
|
---|
| 114 | and <a href="qpainter.html#setWindow">QPainter::setWindow</a>() positions the <em>window</em>, deciding what
|
---|
| 115 | coordinates will be visible. (If you have 3D experience, the window
|
---|
| 116 | is what's usually called projection in 3D.)
|
---|
| 117 | <p> The third step uses the viewport. The viewport too, describes the view
|
---|
| 118 | boundaries, but in device coordinates. The viewport and the windows
|
---|
| 119 | describe the same rectangle, but in different coordinate systems.
|
---|
| 120 | <p> On-screen, the default is the entire <a href="qwidget.html">QWidget</a> or <a href="qpixmap.html">QPixmap</a> where
|
---|
| 121 | you are drawing, which is usually appropriate. For printing this
|
---|
| 122 | function is vital, since very few printers can print over the entire
|
---|
| 123 | physical page.
|
---|
| 124 | <p> So each object to be drawn is transformed into model
|
---|
| 125 | coordinates using <a href="qpainter.html#worldMatrix">QPainter::worldMatrix</a>(), then positioned
|
---|
| 126 | on the drawing device using <a href="qpainter.html#window">QPainter::window</a>() and
|
---|
| 127 | <a href="qpainter.html#viewport">QPainter::viewport</a>().
|
---|
| 128 | <p> It is perfectly possible to do without one or two of the stages. If,
|
---|
| 129 | for example, your goal is to draw something scaled, then just using <a href="qpainter.html#scale">QPainter::scale</a>() makes perfect sense. If your goal is to use a
|
---|
| 130 | fixed-size coordinate system, <a href="qpainter.html#setWindow">QPainter::setWindow</a>() is
|
---|
| 131 | ideal. And so on.
|
---|
| 132 | <p> Here is a short example that uses all three mechanisms: the function
|
---|
| 133 | that draws the clock face in the <a href="aclock-example.html">aclock/aclock.cpp</a> example. We
|
---|
| 134 | recommend compiling and running the example before you read any
|
---|
| 135 | further. In particular, try resizing the window to different sizes.
|
---|
| 136 | <p>
|
---|
| 137 |
|
---|
| 138 | <pre> void AnalogClock::drawClock( <a href="qpainter.html">QPainter</a> *paint )
|
---|
| 139 | {
|
---|
| 140 | <a name="x2275"></a> paint-><a href="qpainter.html#save">save</a>();
|
---|
| 141 | </pre>
|
---|
| 142 | <p> Firstly, we save the painter's state, so that the calling function
|
---|
| 143 | is guaranteed not to be disturbed by the transformations we're going
|
---|
| 144 | to use.
|
---|
| 145 | <p> <pre> <a name="x2277"></a> paint-><a href="qpainter.html#setWindow">setWindow</a>( -500,-500, 1000,1000 );
|
---|
| 146 | </pre>
|
---|
| 147 | <p> We set the model coordinate system we want a 1000*1000 window where
|
---|
| 148 | 0,0 is in the middle.
|
---|
| 149 | <p> <pre> <a name="x2278"></a> <a href="qrect.html">QRect</a> v = paint-><a href="qpainter.html#viewport">viewport</a>();
|
---|
| 150 | <a name="x2282"></a><a name="x2279"></a> int d = QMIN( v.<a href="qrect.html#width">width</a>(), v.<a href="qrect.html#height">height</a>() );
|
---|
| 151 | </pre>
|
---|
| 152 | <p> The device may not be square and we want the clock to be, so we find
|
---|
| 153 | its current viewport and compute its shortest side.
|
---|
| 154 | <p> <pre> <a name="x2280"></a><a name="x2276"></a> paint-><a href="qpainter.html#setViewport">setViewport</a>( v.<a href="qrect.html#left">left</a>() + (v.<a href="qrect.html#width">width</a>()-d)/2,
|
---|
| 155 | <a name="x2281"></a> v.<a href="qrect.html#top">top</a>() + (v.<a href="qrect.html#height">height</a>()-d)/2, d, d );
|
---|
| 156 | </pre>
|
---|
| 157 | <p> Then we set a new square viewport, centered in the old one.
|
---|
| 158 | <p> We're now done with our view. From this point on, when we draw in a
|
---|
| 159 | 1000*1000 area around 0,0, what we draw will show up in the largest
|
---|
| 160 | possible square that'll fit in the output device.
|
---|
| 161 | <p> Time to start drawing.
|
---|
| 162 | <p> <pre> <a href="qpointarray.html">QPointArray</a> pts;
|
---|
| 163 | </pre>
|
---|
| 164 | <p> <em>pts</em> is just a temporary variable to hold some points.
|
---|
| 165 | <p> Next come three drawing blocks, one for the hour hand, one for the
|
---|
| 166 | minute hand and finally one for the clock face itself. First we draw
|
---|
| 167 | the hour hand:
|
---|
| 168 | <p> <pre> paint-><a href="qpainter.html#save">save</a>();
|
---|
| 169 | <a name="x2274"></a> paint-><a href="qpainter.html#rotate">rotate</a>( 30*(time.hour()%12-3) + time.minute()/2 );
|
---|
| 170 | </pre>
|
---|
| 171 | <p> We save the painter and then rotate it so that one axis points along
|
---|
| 172 | the hour hand.
|
---|
| 173 | <p> <pre> pts.setPoints( 4, -20,0, 0,-20, 300,0, 0,20 );
|
---|
| 174 | <a name="x2271"></a> paint-><a href="qpainter.html#drawConvexPolygon">drawConvexPolygon</a>( pts );
|
---|
| 175 | </pre>
|
---|
| 176 | <p> We set <em>pts</em> to a four-point polygon that looks like the hour hand at
|
---|
| 177 | three o'clock, and draw it. Because of the rotation, it's drawn
|
---|
| 178 | pointed in the right direction.
|
---|
| 179 | <p> <pre> <a name="x2273"></a> paint-><a href="qpainter.html#restore">restore</a>();
|
---|
| 180 | </pre>
|
---|
| 181 | <p> We restore the saved painter, undoing the rotation. We could also
|
---|
| 182 | call rotate( -30 ) but that might introduce rounding errors, so it's
|
---|
| 183 | better to use save() and restore(). Next, the minute hand, drawn
|
---|
| 184 | almost the same way:
|
---|
| 185 | <p> <pre> paint-><a href="qpainter.html#save">save</a>();
|
---|
| 186 | paint-><a href="qpainter.html#rotate">rotate</a>( (time.minute()-15)*6 );
|
---|
| 187 | pts.setPoints( 4, -10,0, 0,-10, 400,0, 0,10 );
|
---|
| 188 | paint-><a href="qpainter.html#drawConvexPolygon">drawConvexPolygon</a>( pts );
|
---|
| 189 | paint-><a href="qpainter.html#restore">restore</a>();
|
---|
| 190 | </pre>
|
---|
| 191 | <p> The only differences are how the rotation angle is computed and the
|
---|
| 192 | shape of the polygon.
|
---|
| 193 | <p> The last part to be drawn is the clock face itself.
|
---|
| 194 | <p> <pre> for ( int i=0; i<12; i++ ) {
|
---|
| 195 | <a name="x2272"></a> paint-><a href="qpainter.html#drawLine">drawLine</a>( 440,0, 460,0 );
|
---|
| 196 | paint-><a href="qpainter.html#rotate">rotate</a>( 30 );
|
---|
| 197 | }
|
---|
| 198 | </pre>
|
---|
| 199 | <p> Twelve short hour lines at thirty-degree intervals. At the end of
|
---|
| 200 | that, the painter is rotated in a way which isn't very useful, but
|
---|
| 201 | we're done with painting so that doesn't matter.
|
---|
| 202 | <p> <pre> paint-><a href="qpainter.html#restore">restore</a>();
|
---|
| 203 | }
|
---|
| 204 | </pre>
|
---|
| 205 | <p> The final line of the function restores the painter, so that the
|
---|
| 206 | caller won't be affected by all the transformations we've done.
|
---|
| 207 | <p>
|
---|
| 208 | <!-- eof -->
|
---|
| 209 | <p><address><hr><div align=center>
|
---|
| 210 | <table width=100% cellspacing=0 border=0><tr>
|
---|
| 211 | <td>Copyright © 2007
|
---|
| 212 | <a href="troll.html">Trolltech</a><td align=center><a href="trademarks.html">Trademarks</a>
|
---|
| 213 | <td align=right><div align=right>Qt 3.3.8</div>
|
---|
| 214 | </table></div></address></body>
|
---|
| 215 | </html>
|
---|