hakeの日記

Windows環境でプログラミングの勉強をしています。

アニメーション?

Ruby/Qteの勉強 その28

ボタンを押すとアイコンイメージが画面を移動します。
イメージを表示するQCanvasのオブジェクト@fieldを作成、メインウィンドウ上に表示枠としてQCanvasViewのオブジェクト@fieldviewを配置して、そこから@fieldを覗くイメージです。@field上にアイコンイメージオブジェクト@imageを配置。

require "qtecanvas"      # 追加
include Qtecanvas        # 追加


@field = QCanvas.new( 640, 310 )              # キャンバス作成
@fieldView = QCanvasView.new( @field, self)   # 表示枠作成
@fieldView.setGeometry(0,100,640,350)

@image = Img.new( "/home/QtPalmtop/pics144/Games.png", @field)
@image.show                    # @image表示
@image.setAnimated(false)      # アニメーション禁止
@image.setX(100)               # 座標設定
@image.setY(100)
@image.setVelocity(5, 5)       # 速度設定

@field.update                  # キャンバス更新


移動開始ボタンが押されるとmove_imageメソッドが実行されます。このメソッドは無限ループ構造をしていて@image.advance(1)が実行される度にイメージオブジェクト@imageがsetVelocityで設定されただけ移動します。停止ボタンを受け付けるためこのメソッドはスレッドのブロックにしています。

def move_image
   @stop = false
   t = Thread.new{ # 停止可能とするためスレッドにする
      Thread.pass
      loop{
         if @stop           # 停止ボタン処理
            break
         end
         (中略)
         @image.advance(1)  # 1コマ移動?
         @field.update      # キャンバス更新
      }
   }
end


イメージ表示用のクラスとしてImgをQRCanvasRectangleから継承して作成しています。ここで良くわからないのがスーパークラスがQCanvasRectangleでなくてQRCanvasRectangleであること。元ネタのページに少し説明がありますが、よく理解できていません。はっきりしているのはQRCanvasRectangleから継承しないとdrawShapeメソッド?が機能しないので画像ではなく四角枠になってしまうということ。

#!/usr/bin/env ruby

require "qte"
require "qpe"
require "qtecanvas"      # 追加
require "thread"         # 追加

include Qte
include Qpe
include Qtecanvas        # 追加


class SampleWindow < QMainWindow
   def initialize()
      super()
      setCaption(tr("サンプル"))
      @msg = QLabel.new(tr("Canvas表示のサンプル"),self)
      @msg.setGeometry(0,0,310,35)
      @msg1 = QLabel.new("Pos:",self)
      @msg1.setGeometry(0,40,600,35)

      @field = QCanvas.new( 640, 310 )              # キャンバス作成
      @fieldView = QCanvasView.new( @field, self)   # 表示枠作成
      @fieldView.setGeometry(0,100,640,350)

#      @image = Img.new( "/home/QtPalmtop/pics/Zaurus_logo.png", @field )
      @image = Img.new( "/home/QtPalmtop/pics144/Games.png", @field)
      @image.show                    # @image表示
      @image.setAnimated(false)      # アニメーション禁止
      @image.setX(100)               # 座標設定
      @image.setY(100)
      @image.setVelocity(5, 5)       # 速度設定

      @field.update                  # キャンバス更新

      @pb1 = QPushButton.new( tr("移動開始"), self)
      @pb1.setGeometry(320,5,100,30)
      connect(@pb1, QSIGNAL("clicked()"), self, 'move_image')

      @pb2 = QPushButton.new( tr("停止"), self)
      @pb2.setGeometry(420,5,100,30)
      connect(@pb2, QSIGNAL("clicked()"), self, 'stop')

      @stop = false

   end

   def move_image
#      @image.move( rand(600), rand(200))
      @stop = false

      t = Thread.new{ # 停止可能とするためスレッドにする
         Thread.pass
         loop{
            if @stop           # 停止ボタン処理
               break
            end

            x, y = @image.pos  # 現在位置取得
            vx,vy = @image.vel # 現在速度取得
            @msg1.setText("Pos: x=#{x}, y=#{y} Velocity: vx=#{vx}, vy=#{vy}")

            changeVelocity( @image )
            @image.advance(1)  # 1コマ移動?
            @field.update      # キャンバス更新
         }
      }
   end

   def changeVelocity( item ) # 移動方向の変更
      flag = false
      x, y = item.pos         # 現在位置取得
      vx,vy = item.vel        # 現在速度取得

      if x > 640 || x < 0
         vx = vx * -1
         flag = true
      end
      if y > 310 || y < 0
         vy = vy * -1
         flag = true
      end
      if flag
         item.setAnimated(false) # 一旦falseにしないとダメ
         item.setVelocity(vx, vy)
         item.setAnimated(true)
      end
      return vx, vy
   end

   def stop
     @stop = true
   end
end

class Img < QRCanvasRectangle   # QCanvasRectangleではない
   def initialize( filepath, parent )  # 引数にfailepathを追加
      super( parent )
      @pix = QPixmap.new(filepath)
#      @pix = QPixmap.new("/home/QtPalmtop/pics/Zaurus_logo.png")
      setSize( @pix.width, @pix.height)
      @hx = @pix.width / 2
      @hy = @pix.height / 2
   end

   def pos
      return self.x, self.y
   end

   def vel
      return self.xVelocity, self.yVelocity
   end

   def move( x, y )
      super(x - @hx, y - @hy)
   end

# 画像ファイルの描画
# QR……でないと使えない
# QPolygonalItemのProtectedメンバー
# 引数はQPainter
# show,advanceで呼ばれる?
  def drawShape( p ) 
     p.drawPixmap(x, y, @pix)
  end
end

$defaultCodec = QTextCodec.codecForName("utf8")
app = QPEApplication.new([$0]+ARGV)
app.setDefaultCodec($defaultCodec)
QApplication.setFont(QFont.new("lcfont",18))
app.showMainWidget(SampleWindow.new)
app.exec