2月 04, 2009

【翻譯】Qt Tutorial 10 - Smooth as Silk

@
tutorials/tutorial/t10/cannonfield.cpp
tutorials/tutorial/t10/cannonfield.h
tutorials/tutorial/t10/lcdrange.cpp
tutorials/tutorial/t10/lcdrange.h
tutorials/tutorial/t10/main.cpp
tutorials/tutorial/t10/t10.pro

  在這個範例中,我們加入了力量(force)控制。




Line by Line Walkthrough

t10/cannonfield.h

  CannonField 現在除了角度外,又多了一個力量值。

     int angle() const { return currentAngle; }
     int force() const { return currentForce; }

 public slots:
     void setAngle(int angle);
     void setForce(int force);

 signals:
     void angleChanged(int newAngle);
     void forceChanged(int newForce);

  力量的介面遵循著與角度同樣的寫法。

 private:
     QRect cannonRect() const;

  我們將加農砲的封裝矩形定義放到一個單獨的函式中。

     int currentAngle;
     int currentForce;
 };

  力量被存在一個 currentForce 變數中。

t10/cannonfield.cpp

 CannonField::CannonField(QWidget *parent)
     : QWidget(parent)
 {
     currentAngle = 45;
     currentForce = 0;
     setPalette(QPalette(QColor(250, 250, 200)));
     setAutoFillBackground(true);
 }

  力量被初始為零。

 void CannonField::setAngle(int angle)
 {
     if (angle < 5)
         angle = 5;
     if (angle > 70)
         angle = 70;
     if (currentAngle == angle)
         return;
     currentAngle = angle;
     update(cannonRect());
     emit angleChanged(currentAngle);
 }

  我們在 setAngle() 函式中做一點細微的改變。它只會重繪元件中包含加農砲的那一部分。

 void CannonField::setForce(int force)
 {
     if (force < 0)
         force = 0;
     if (currentForce == force)
         return;
     currentForce = force;
     emit forceChanged(currentForce);
 }

  setForce() 的實現與 setAngle() 相當類似。它們唯一的不同是因為我們沒有顯示出力量值,所以我們不需要重繪元件。

 void CannonField::paintEvent(QPaintEvent * /* event */)
 {
     QPainter painter(this);

     painter.setPen(Qt::NoPen);
     painter.setBrush(Qt::blue);

     painter.translate(0, height());
     painter.drawPie(QRect(-35, -35, 70, 70), 0, 90 * 16);
     painter.rotate(-currentAngle);
     painter.drawRect(QRect(30, -5, 20, 10));
 }

  我們像第九章一樣畫出來。

 QRect CannonField::cannonRect() const
 {
     QRect result(0, 0, 50, 50);
     result.moveBottomLeft(rect().bottomLeft());
     return result;
 }

  cannonRect() 函式返回在元件座標中封裝加農砲的矩形。首先我們建立一個 50 x 50 的矩形,然後移動它。所以它的左下角與元件的左下角是相同的。

  QWidget::rect() 函式返回元件自身座標的封裝矩形。矩形的左上角永遠是 (0, 0)。

t10/main.cpp

 MyWidget::MyWidget(QWidget *parent)
     : QWidget(parent)
 {

  建構子大致上相同,不過加入了一些新東西。

     LCDRange *force = new LCDRange;
     force->setRange(10, 50);

  我們加入了第二個 LCDRange,它將會被用來設定力量值。

     connect(force, SIGNAL(valueChanged(int)),
             cannonField, SLOT(setForce(int)));
     connect(cannonField, SIGNAL(forceChanged(int)),
             force, SLOT(setValue(int)));

  我們將連結 force 元件與 cannonField 元件,就像我們為 angle 元件所做的。

     QVBoxLayout *leftLayout = new QVBoxLayout;
     leftLayout->addWidget(angle);
     leftLayout->addWidget(force);

     QGridLayout *gridLayout = new QGridLayout;
     gridLayout->addWidget(quit, 0, 0);
     gridLayout->addLayout(leftLayout, 1, 0);
     gridLayout->addWidget(cannonField, 1, 1, 2, 1);
     gridLayout->setColumnStretch(1, 10);

  在第九章,我們把 angle 放在版面配置的左下那格。現在我們想要讓兩個元件放在同一格裡,所以我們做了一個直的盒子(vertical box),把直的盒子放在網格中,並把 anglerange 元件放在直的盒子裡。

     force->setValue(25);

  我們將力量值初始為 25。


Running the Application

  我們現在有力量控制了。


Exercises

  使加農砲的砲管大小依據力量值變化。

  把加農砲放在右下角。

  試著加入更好的鍵盤介面。例如,讓 +- 來增加和減少力量值,並使用 enter 發射。假如你對左方向鍵右方向鍵的運作方式感到苦惱,也把它改掉吧。[提示:重新實現 QWidget::keyPressEvent()。]


來源:Qt Tutorial 10 - Smooth as Silk
版本:4.4.3

0 回覆:

張貼留言