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

    From KDE TechBase

    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()。]