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

📄 t8.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 8: Preparing for Battle</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 8: Preparing for Battle</h1><br clear="all"><p><center><img src="t8.png" alt="Screenshot of tutorial eight"></center><p>In this example, we introduce the first custom widget that can paintitself.  We also add a useful keyboard interface (with two lines ofcode).<p><ul><li><a href="t8-lcdrange-h.html">lcdrange.h</a> contains the LCDRangeclass definition<li><a href="t8-lcdrange-cpp.html">lcdrange.cpp</a> contains the LCDRangeimplementation<li><a href="t8-cannon-h.html">cannon.h</a> contains the CannonField classdefinition<li><a href="t8-cannon-cpp.html">cannon.cpp</a> contains the CannonFieldimplementation<li><a href="t8-main-cpp.html">main.cpp</a> contains MyWidget and main.<li><a href="t8-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="t8-lcdrange-h.html">lcdrange.h</a></h3><p>This file is very similar to the lcdrange.h in chapter 7.  We have addedone slot, setRange().   <pre>        void setRange( int minVal, int maxVal );</pre><p>We now add the possibility of setting the range of the LCDRange.Until now, it has been fixed at 0..99.<p><h3><a href="t8-lcdrange-cpp.html">lcdrange.cpp</a></h3> <p>There is a change to the constructor, we'll discuss that later.  <pre>    void LCDRange::setRange( int minVal, int maxVal )    {        if ( minVal &lt; 0 || maxVal &gt; 99 || minVal &gt; maxVal ) {          <a href="qapplication.html#290ef4">qWarning</a>( "LCDRange::setRange(%d,%d)\n"                   "\tRange must be 0..99\n"                   "\tand minVal must not be greater than maxVal",                   minVal, maxVal );          return;        }        slider-&gt;setRange( minVal, maxVal );    }</pre><p>setRange() sets the range of the slider in the LCDRange.  Since wehave set up the QLCDNumber to always display two digits, we want tolimit the possible range of <code>minVal</code> and <code>maxVal</code> to 0..99 to avoidoverflow of the QLCDNumber.  (We could have allowed values down to -9but chose not to.)  If the arguments are illegal, we use Qt'sqWarning() function to issue a warning to the user and returnimmediately.  qWarning() is a printf-like function that by defaultsends its output to <code>stderr.</code>  You can install your own handlerfunction using <a href="qapplication.html#a8a31b">::qInstallMsgHandler()</a> if you want.<p><h3><a href="t8-cannon-h.html">cannon.h</a></h3><p>CannonField is a new custom widget that knows how to display itself.    <pre>    class CannonField : public QWidget    {        Q_OBJECT    public:        CannonField( <a href="qwidget.html">QWidget</a> *parent=0, const char *name=0 );</pre><p>CannonField inherits QWidget and we use the same idiom as for LCDRange. <pre>        int angle() const { return ang; }        <a href="qsizepolicy.html">QSizePolicy</a> sizePolicy() const;        public slots:        void setAngle( int degrees );        signals:        void angleChanged( int );</pre><p>For the time being, CannonField only contains an angle value for which weprovide an interface using the same idiom as for value in LCDRange. <pre>    protected:        void paintEvent( <a href="qpaintevent.html">QPaintEvent</a> * );</pre><p>This is the second of the many event handlers in QWidget that weencounter.  This virtual function is called by Qt whenever a widget needsto update itself (i.e.  paint the widget's surface).<p><h3><a href="t8-cannon-cpp.html">cannon.cpp</a></h3>   <pre>    CannonField::CannonField( <a href="qwidget.html">QWidget</a> *parent, const char *name )            : <a href="qwidget.html">QWidget</a>( parent, name )    {</pre><p>Again, we use the same idiom as for LCDRange in the previous chapter. <pre>        ang = 45;        <a href="qwidget.html#d7e4b9">setPalette</a>( <a href="qpalette.html">QPalette</a>( <a href="qcolor.html">QColor</a>( 250, 250, 200) ) );    }</pre><p>The constructor initializes the angle value to 45 degrees, and sets acustom palette for this widget.<p>This palette uses the indicated color as background, and picks othercolors suitably.  (For this widget, only the background and textcolors will be used.)  <pre>    void CannonField::setAngle( int degrees )    {        if ( degrees &lt; 5 )            degrees = 5;        if ( degrees &gt; 70 )            degrees = 70;        if ( ang == degrees )            return;        ang = degrees;        <a href="qwidget.html#7569b1">repaint</a>();        emit angleChanged( ang );    }</pre><p>This function sets the angle value.  We have chosen a legal range of5..70 and adjust the given number of degrees accordingly.  We havechosen not to issue a warning if the new angle is out of range.<p>If the new angle equals the old one, we return immediately.  It isimportant to only emit the signal angleChanged() when the angle <em>really</em> has changed.<p>Then we set the new angle value and repaint our widget.  The <a href="qwidget.html#7569b1">QWidget::repaint()</a> function clears the widget (usually filling it withits background color) and send a paint event to the widget.  Thisresults in a call the paint event function of the widget.<p>Finally, we emit the angleChanged() signal to tell the outside worldthat the angle has changed.  The <code>emit</code> keyword is unique to Qt andnot regular C++ syntax.  In fact, it is a macro.  <pre>    void CannonField::paintEvent( <a href="qpaintevent.html">QPaintEvent</a> * )    {        <a href="qstring.html">QString</a> s = "Angle = " + QString::number( ang );        <a href="qpainter.html">QPainter</a> p( this );        p.<a href="qpainter.html#0f088f">drawText</a>( 200, 200, s );    }</pre><p>This is our first attempt to write a paint event handler.  The eventargument contains a description of the paint event.  <a href="qpaintevent.html">QPaintEvent</a>contains the region in the widget that must be updated.  For the timebeing, we will be lazy and just paint everything.<p>Our code displays the angle value in the widget at a fixed position.First we create a QString with some text and the angle, then we createa QPainter operating on this widget, and use it to paint the string.We'll come back to QPainter later; it can do a great many things.<p><h3><a href="t8-main-cpp.html">main.cpp</a></h3>   <pre>    #include "cannon.h"</pre><p>We include our new class.  <pre>    class MyWidget: public QWidget    {    public:        MyWidget( <a href="qwidget.html">QWidget</a> *parent=0, const char *name=0 );    };</pre><p>This time, we include a single LCDRange and a CannonField in our top levelwidget.  <pre>        LCDRange *angle = new LCDRange( this, "angle" );</pre><p>In the constructor, we create and set up our LCDRange. <pre>        angle-&gt;setRange( 5, 70 );</pre><p>We set the LCDRange to accept ranges from 5 to 70 degrees. <pre>        CannonField *cannonField             = new CannonField( this, "cannonField" );</pre><p>We create our CannonField. <pre>        <a href="qobject.html#fbde73">connect</a>( angle, SIGNAL(valueChanged(int)),                 cannonField, SLOT(setAngle(int)) );        <a href="qobject.html#fbde73">connect</a>( cannonField, SIGNAL(angleChanged(int)),                 angle, SLOT(setValue(int)) );</pre><p>Here we connect the valueChanged() signal of the LCDRange to thesetAngle() slot of the CannonField.  This will update CannonField's anglevalue whenever the user operates the LCDRange.  We also make the reverseconnection, so that changing the angle in the CannonField will update theLCDRange value.  In our example, we never change the angle of theCannonField directly, but by doing the last connect(), we ensure that nofuture changes will disrupt the synchronization between those two values.<p>This illustrates the power of component programming and properencapsulation.<p>Notice how important it is to only emit the angleChanged() signal whenthe angle actually changes.  If both the LCDRange and the CannonFieldhad omitted this check, the program would have entered an infiniteloop upon the first change of one of the values. <pre>        <a href="qgridlayout.html">QGridLayout</a> *grid = new <a href="qgridlayout.html">QGridLayout</a>( this, 2, 2, 10 );        //2x2, 10 pixel border</pre><p>Until now we've used the no-assembly-required QVBox and QGrid widgetsfor geometry management.  However, now we want to have a little morecontrol over the layout, and switch to the more powerful QGridLayoutclass.  QGridLayout isn't a widget, it is a different class that canmanage the children of <em>any</em> widget.<p>As the comment indicates, we create a two-by-two array, with ten pixelborders.  (The constructor for <a href="qgridlayout.html">QGridLayout</a> can be a little cryptic,so it's good to put in such comments.) <pre>        grid-&gt;<a href="qgridlayout.html#dac29c">addWidget</a>( quit, 0, 0 );</pre><p>We add the Quit button in the top-left cell of the grid: 0, 0. <pre>        grid-&gt;<a href="qgridlayout.html#dac29c">addWidget</a>( angle, 1, 0, Qt::AlignTop );</pre><p>We put the angle LCDRange in the bottom-left cell, aligned to the topof its cell.  (This alignment is one of the things QGridLayout allowsbut QGrid does not.) <pre>        grid-&gt;<a href="qgridlayout.html#dac29c">addWidget</a>( cannonField, 1, 1 );</pre><p>We put the CannonField object in the bottom right cell.  (The topright cell is empty, yes.) <pre>        grid-&gt;<a href="qgridlayout.html#df80c4">setColStretch</a>( 1, 10 );</pre><p>We tell QGridLayout that the right column (column 1) is stretchable.Since the left column isn't (it has stretch factor 0 - the defaultvalue), QGridLayout will try to let the left-hand widgets' sizes beunchanged and resize just the CannonField when the MyWidget isresized. <pre>        angle-&gt;setValue( 60 );</pre><p>We set an initial angle value.  Note that this will trigger theconnection from LCDRange to CannonField. <pre>        angle-&gt;<a href="qwidget.html#25775a">setFocus</a>();</pre><p>And our last action is to set <code>angle</code> to have keyboard focus, so thatby default, keyboard input will go to the LCDRange widget.<p>LCDRange does not contain any keyPressEvent(), so that would seem notto be terribly useful.  However, its constructor just got a new line:   <pre>        <a href="qwidget.html#cddadb">setFocusProxy</a>( slider );</pre><p>The LCDRange sets the slider to be its focus proxy.  That means thatwhen someone (the program or the user) wants to give the LCDRangekeyboard focus, the slider should take care of it.  QSlider has a decentkeyboard interface, so with just one line of code we've give LCDRangeone.<p><h2>Behavior</h2><p>The keyboard now does something - the arrow keys, Home, End, PageUpand PageDown now all do something vaguely sensible.<p>When the slider is operated, the CannonField displays the new anglevalue.  Upon resize, CannonField is gives as much space as possible.<p>On Windows machines with an 8-bit display, the new background color isdithered to death.  The next chapter works around this.<p><h2>Exercises</h2><p>Try to resize the window.  What happens if you make it really narrowor really squat?<p>If you remove the AlignTop, what happens to the LCDRange's positionand size?  Why?<p>If you give the left-hand column a non-zero stretch factor, whathappens when you resize the window?<p>Leave out the setFocus() call.  Which behavior do you prefer?<p>Try to change "Quit" to "&Quit" in the QButton::setText() call.  Howdoes the button's look change?  What happens if you press Alt-Q whilethe program's running?  (Meta-Q on a few keyboards.)<p>Center the text in the CannonField.<p>You may now go on to <a href="t9.html">chapter nine.</a><p>[<a href="t7.html">Previous tutorial</a>][<a href="t9.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 + -