⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 t12.html

📁 qtopiaphone英文帮助,用于初学者和开发人员,初学者可以用来学习,开发人员可以用来资料查询.
💻 HTML
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"><html><head><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><title>Qt Tutorial - Chapter 12: Hanging in the Air the Way Bricks Don't</title></head><body bgcolor="#ffffff"><p><table width="100%"><tr><td><a href="index.html"><img width="100" height="100" src="qtlogo.png"alt="Home" border="0"><img width="100"height="100" src="face.png" alt="Home" border="0"></a><td valign="top"><div align="right"><img src="dochead.png" width="472" height="27"><br><a href="classes.html"><b>Classes</b></a>- <a href="annotated.html">Annotated</a>- <a href="hierarchy.html">Tree</a>- <a href="functions.html">Functions</a>- <a href="index.html">Home</a>- <a href="topicals.html"><b>Structure</b>  <font face="Arial,Helvetica,Geneva,Swiss,SunSans-Regular" align="center" size=32>Qte</font></a></div></table><p><h1 align=center>Chapter 12: Hanging in the Air the Way Bricks Don't</h1><br clear="all"><p><center><img src="t12.png" alt="Screenshot of tutorial twelve"></center><p>In this example, we extend our LCDRange class to include a text label.We also provide something to shoot at.<p><ul><li><a href="t12-lcdrange-h.html">lcdrange.h</a> contains the LCDRangeclass definition<li><a href="t12-lcdrange-cpp.html">lcdrange.cpp</a> contains the LCDRangeimplementation<li><a href="t12-cannon-h.html">cannon.h</a> contains the CannonField classdefinition<li><a href="t12-cannon-cpp.html">cannon.cpp</a> contains the CannonFieldimplementation<li><a href="t12-main-cpp.html">main.cpp</a> contains MyWidget and main.<li><a href="t12-makefile.html">Makefile</a> contains some rules forgenerating the meta object information necessary for <ahref="signalsandslots.html">signal/slot creation.</a></ul><p><h2>Line by Line Walk-Through</h2><p><h3><a href="t12-lcdrange-h.html">lcdrange.h</a></h3><p>The LCDRange now has a text label.   <pre>    class QLabel;</pre><p>We name declare QLabel since we want to use a pointer to it in the classdefinition.  <pre>    class LCDRange : public QVBox    {        Q_OBJECT    public:        LCDRange( <a href="qwidget.html">QWidget</a> *parent=0, const char *name=0 );        LCDRange( const char *s, QWidget *parent=0,                  const char *name=0 );</pre><p>We have added a new constructor that sets the label text in addition tothe parent and name.  <pre>        const char *text()  const;</pre><p>This function returns the label text.  <pre>        void setText( const char * );</pre><p>This slot sets the label text.  <pre>    private:        void init();</pre><p>Since we now have two constructors, we have chosen to put the commoninitialization in the private init() function.  <pre>        <a href="qlabel.html">QLabel</a>      *label;</pre><p>We also have a new private variable; a QLabel.  QLabel is one of Qt'sstandard widgets and can show a text or a pixmap with or without aframe.<p><h3><a href="t12-lcdrange-cpp.html">lcdrange.cpp</a></h3>   <pre>    #include &lt;<a href="qlabel-h.html">qlabel.h</a>&gt;</pre><p>Here we include the QLabel class definition.  <pre>    LCDRange::LCDRange( <a href="qwidget.html">QWidget</a> *parent, const char *name )            : <a href="qvbox.html">QVBox</a>( parent, name )    {        init();    }</pre><p>This constructor calls the init() function, which contains the commoninitialization code.  <pre>    LCDRange::LCDRange( const char *s, QWidget *parent,                        const char *name )            : <a href="qvbox.html">QVBox</a>( parent, name )    {        init();        setText( s );    }</pre><p>This constructor first calls init(), then sets the label text.  <pre>    void LCDRange::init()    {        <a href="qlcdnumber.html">QLCDNumber</a> *lcd  = new <a href="qlcdnumber.html">QLCDNumber</a>( 2, this, "lcd"  );        slider = new <a href="qslider.html">QSlider</a>( Horizontal, this, "slider" );        slider-&gt;setRange( 0, 99 );        slider-&gt;setValue( 0 );            label = new <a href="qlabel.html">QLabel</a>( " ", this, "label"  );        label-&gt;setAlignment( AlignCenter );            <a href="qobject.html#fbde73">connect</a>( slider, SIGNAL(valueChanged(int)),                 lcd, SLOT(display(int)) );        <a href="qobject.html#fbde73">connect</a>( slider, SIGNAL(valueChanged(int)),                 SIGNAL(valueChanged(int)) );            <a href="qwidget.html#cddadb">setFocusProxy</a>( slider );    }</pre><p>The set up of <code>lcd</code> and <code>slider</code> is the same as in the previouschapter.  Next, we create a QLabel and tell it to align the contentscentered (both vertically and horizontally).  The connect() statementshave also been taken from the previous chapter.  <pre>    const char *LCDRange::text() const    {        return label-&gt;text();    }</pre><p>This function returns the label text.  <pre>    void LCDRange::setText( const char *s )    {        label-&gt;setText( s );    }</pre><p>This function sets the label text.<p><h3><a href="t12-cannon-h.html">cannon.h</a></h3><p>The CannonField now has two new signals: hit() and missed().  In additionit contains a target.    <pre>        void  newTarget();</pre><p>This slot creates a target at a new position.  <pre>    signals:        void  hit();        void  missed();</pre><p>The hit() signal is emitted when a shot hits the target.  The missed()signal is emitted when the shot moves beyond the right or bottom edgeof the widget (i.e.  it has is certain that it has not and will nothit the target).  <pre>        void  paintTarget( <a href="qpainter.html">QPainter</a> * );</pre><p>This private function paints the target.  <pre>        <a href="qrect.html">QRect</a> targetRect() const;</pre><p>This private function returns the enclosing rectangle of the target.  <pre>        <a href="qpoint.html">QPoint</a> target;</pre><p>This private variable contains the center point of the target.<p><h3><a href="t12-cannon-cpp.html">cannon.cpp</a></h3>   <pre>    #include &lt;<a href="qdatetime-h.html">qdatetime.h</a>&gt;</pre><p>We include the QDate, QTime and QDateTime class definitions.  <pre>    #include &lt;stdlib.h&gt;</pre><p>We include the stdlib library because we need the rand() function.  <pre>        newTarget();</pre><p>This line has been added to the constructor.  It creates a "random"position for the target.  In fact, the newTarget() function will tryto paint the target.  Since we are in a constructor, the CannonFieldwidget is invisible.  Qt guarantees that no harm is done when callingrepaint() on a hidden widget.  <pre>    void  CannonField::newTarget()    {        static bool first_time = TRUE;        if ( first_time ) {            first_time = FALSE;            <a href="qtime.html">QTime</a> midnight( 0, 0, 0 );            srand( midnight.<a href="qtime.html#0b9e38">secsTo</a>(<a href="qtime.html#6091a9">QTime::currentTime</a>()) );        }        <a href="qregion.html">QRegion</a> r( targetRect() );        target = QPoint( 200 + rand() % 190,                         10  + rand() % 255 );        <a href="qwidget.html#7569b1">repaint</a>( r.<a href="qrect.html#81e8a3">unite</a>( targetRect() ) );    }</pre><p>This private function creates a target center point at a new "random"position.<p>We use the rand() function to fetch random integers.  The rand() functionnormally returns the same series of numbers each time you run a program.This would make the target appear at the same position every time.  Toavoid this, we must set a random seed the first time this function iscalled.  The random seed must also be random in order to avoid equal randomnumber series.  The solution is to use the number of seconds that havepassed since midnight as a pseudo-random value.<p>First we create a static bool local variable.  A static variable likethis one is guaranteed to keep its value between calls to the function.<p>The <code>if</code> test will only succeed the first time this function is called,because we set <code>first_time</code> to FALSE inside the <code>if</code> block.<p>Then we create the QTime object <code>midnight</code> which represents the time00:00:00.  Next, we fetch the number of seconds from midnight untilnow and use it as a random seed.  See the documentation for <a href="qdate.html">QDate</a>,<a href="qtime.html">QTime</a> and <a href="qdatetime.html">QDateTime</a> for more information.<p>Finally, we calculate the target's center point.  We keep it withinthe rectangle (x=200,y=35,width=190,height=255), (i.e.  the possiblex and y values are x = 200..390 and y = 35..290) in a coordinate systemwhere we put y position 0 at the bottom edge of the widget and lety values increase upwards.  x is as normal, with 0 at the left edge andwith x values increasing to the right.<p>By experimentation, we have found this to always be in reach of the shot.<p>Note that rand() return a random integer >= 0.  <pre>    void CannonField::moveShot()    {        <a href="qregion.html">QRegion</a> r( shotRect() );        timerCount++;            <a href="qrect.html">QRect</a> shotR = shotRect();</pre><p>This part of the timer event has not changed from the previous chapter. <pre>        if ( shotR.<a href="qrect.html#5b3d2b">intersects</a>( targetRect() ) ) {            autoShootTimer-&gt;stop();            emit hit();</pre><p>This <code>if</code> statement checks if the shot rectangle intersects thetarget rectangle.  If it does, the shot has hit the target (ouchh!).We stop the shoot timer and emit the hit() signal to tell the outsideworld that a target was destroyed and return.<p>Note that we could have created a new target on the spot, but since theCannonField is a component, we leave such decisions to the user of thecomponent. <pre>        } else if ( shotR.<a href="qrect.html#fccae7">x</a>() &gt; width() || shotR.<a href="qrect.html#f448f7">y</a>() &gt; height() ) {            autoShootTimer-&gt;stop();            emit missed();</pre><p>This <code>if</code> statement is the same as in the previous chapter, except thatit now emits the missed() signal to tell the outside world about thefailure. <pre>        } else {</pre><p>And the rest of the function is as before.<p>CannonField::paintEvent() is as before, except that this has beenadded:   <pre>        if ( updateR.<a href="qrect.html#5b3d2b">intersects</a>( targetRect() ) )            paintTarget( &amp;p );</pre><p>These two lines make sure the target too is painted, when necessary.  <pre>    void CannonField::paintTarget( <a href="qpainter.html">QPainter</a> *p )    {        p-&gt;<a href="qpainter.html#3e0cc8">setBrush</a>( red );        p-&gt;<a href="qpainter.html#0183e4">setPen</a>( black );        p-&gt;<a href="qpainter.html#4c0077">drawRect</a>( targetRect() );    }</pre><p>This private function paints the target; a rectangle filled with red andwith a black outline.  <pre>    <a href="qrect.html">QRect</a> CannonField::targetRect() const    {        <a href="qrect.html">QRect</a> r( 0, 0, 20, 10 );        r.<a href="qrect.html#03af30">moveCenter</a>( <a href="qpoint.html">QPoint</a>(target.x(),<a href="qwidget.html#e3c588">height</a>() - 1 - target.y()) );        return r;    }</pre><p>This private function returns the enclosing rectangle of the target.Remember from newTarget() that the <code>target</code> point uses y coordinate 0 atthe bottom of the widget.  We calculate the point in widget coordinatesbefore we call <a href="qrect.html#03af30">QRect::moveCenter()</a>.<p>The reason we have chosen this coordinate mapping is to fix the distancebetween the target and the bottom of the widget.  Remember that the widgetcan be resized by the user or the program at any time.<p><h3><a href="t12-main-cpp.html">main.cpp</a></h3> <p>There are no new members in the MyWidget class, but we have slightlychanged the constructor to set the new LCDRange text labels.   <pre>        LCDRange *angle  = new LCDRange( "ANGLE", this, "angle" );</pre><p>We set the angle text label to "ANGLE".  <pre>        LCDRange *force  = new LCDRange( "FORCE", this, "force" );</pre><p>We set the force text label to "FORCE".<p><h2>Behavior</h2><p>The cannon can shoot at a target and a new target is automatically createdwhen one has been hit.<p>The LCDRange widgets look a bit strange - the built-in layoutmanagement in QVBox gives the labels too much space and the rest notenough.  We'll fix that in the next chapter.<p><h2>Exercises</h2><p>Make a cheat button that when pressed makes the CannonField displaythe shot trajectory for 5 seconds.<p>If you did the "round shot" exercise from the previous chapter, trychanging the shotRect() to a shotRegion() that returns a <a href="qregion.html">QRegion</a> soyou can have really accurate collision detection.<p>Make a moving target.<p>Make sure the target is always created entirely on-screen.<p>Make sure that the widget cannot be resized so that the target isn'tvisible.  Hint: <a href="qwidget.html#c0b5fb">QWidget::setMinimumSize()</a> is your friend.<p>(Not easy:) Make it possible to have several shots in the air at thesame time.  Hint: make a Shot object.<p>You may now go on to <a href="t13.html">chapter thirteen.</a><p>[<a href="t11.html">Previous tutorial</a>][<a href="t13.html">Next tutorial</a>][<a href="tutorial.html">Main tutorial page</a>]<p><address><hr><div align="center"><table width="100%" cellspacing="0" border="0"><tr><td>Copyright 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -