Archive:Development/Tutorials/Qt4 Ruby Tutorial/Chapter 10 (zh TW)

From KDE TechBase
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

Template:I18n/Language Navigation Bar (zh TW)

Template:TutorialBrowser (zh TW)

Smooth as Silk

檔案:

概覽

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

一行一行的瀏覽

cannon.rb

CannonField 現在除了角度外,又加入力量值。

signals 'angleChanged(int)', 'forceChanged(int)'
slots 'setAngle(int)', 'setForce(int)'

力量的介面遵循和角度相同的寫法。

def initialize(parent = nil)
  super()

  @currentAngle = 45
  @currentForce = 0

  setPalette(Qt::Palette.new(Qt::Color.new(250, 250, 200)))
  setAutoFillBackground(true)
end

力量 @currentForce 初始化為零。

def setAngle(angle)
  if angle < 5
    angle = 5
  elsif angle > 70
    angle = 70
  end

  if @currentAngle == angle
    return
  end

  @currentAngle = angle
  update(cannonRect())
  emit angleChanged(@currentAngle)
end

我們在 setAngle() 函式作了一點輕微的改變。它只有重畫 widget 中包含加農砲的部分。

def setForce(force)
  if force < 0
    force = 0
  end
  if @currentForce == force
    return
  end

  @currentForce = force
  emit forceChanged(@currentForce)
end

setForce() 的實現相當類似 setAngle()。唯一的差別是,因為我們沒有顯示力量值,所以不需要重繪 widget。

def paintEvent(event)
  painter = Qt::Painter.new(self)

  painter.setPen(Qt::NoPen)
  painter.setBrush(Qt::Brush.new(Qt::blue))

  painter.translate(0, height())
  painter.drawPie(Qt::Rect.new(-35, -35, 70, 70), 0, 90 * 16)
  painter.rotate(-@currentAngle)
  painter.drawRect(Qt::Rect.new(30, -5, 20, 10))
  painter.end()
end

我們像第9章一樣繪製。

def cannonRect()
  result = Qt::Rect.new(0, 0, 50, 50)
  result.moveBottomLeft(rect().bottomLeft())
  return result
end

cannonRect() 函式返回 widget 坐標中封裝加農砲的矩形。首先,我們建立一個大小50×50的矩形。然後移動它,所以它的左下角等同於 widget 自己的左下角。

Qt::Widget::rect() 函式返回在 widget 坐標中封裝 widget 自己矩形。矩形的左上角永遠是(0,0)。

t10.rb

建構子大部分相同,但新增了一些東西。

force = LCDRange.new()
force.setRange(10, 50)

我們加入第二個 LCDRange,用來設定力量。

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

我們連接 force widget 和 cannonField widget,就像我們為 angle widget 所作的。

leftLayout = Qt::VBoxLayout.new()
leftLayout.addWidget(angle)
leftLayout.addWidget(force)

gridLayout = Qt::GridLayout.new()
gridLayout.addWidget(quit, 0, 0)
gridLayout.addLayout(leftLayout, 1, 0)
gridLayout.addWidget(cannonField, 1, 1, 2, 1)
gridLayout.setColumnStretch(1, 10)

在第9章中,我們把 angle 放在佈局的左下格。現在,我們想有兩個 widget在該格中,所以我們做一個 vertical box,把 vertical box 放在網格中,並且把 anglerange 放入 vertical box。

force.setValue(25)

我們初始化力量值為25。

執行應用程式

我們現在有力量控制了。

練習

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

把加農砲放在右下角。

嘗試增加一個更好的鍵盤介面。例如,用+和-來增加和減少力量,並用 enter 發射。如果你對方向鍵的運作的方式感到困擾,也更改它吧。[提示:重新實作 Qt::Widget::keyPressEvent()。]