hakeの日記

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

キーイベントの取得

Ruby/Qteの勉強 その30

ここに話題があったので試してみました。前回のプログラムに追加してみる。
画面をタップすると座標を表示、その後カーソルキー操作で数字が移動していきます。


keyPressEventはQKeyが渡されてくるので、ここ(e.key)からキーコードを取得してカーソルキーの場合がキーに応じた移動量をQPointオブジェクト@movePosに保存して、新規に作成したシグナル@pressedでシグナルを発生させる。メイン側のメソッドmovePosはこのシグナルを受けて@movePosに応じた量だけ移動を行っています。


ちなみにkeyPressEventはメイン側(クラスSampleWindow)に置いても同様の動作をしました、この場合はforcusPolicyの設定がなくても動作しました。FieldView上にkeyPressEventを置いた場合はこのオブジェクト上にフォーカスが無いと動作しないという意味?

#!/usr/bin/env ruby

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

include Qte
include Qpe
include Qtecanvas        # 追加


class SampleWindow < QMainWindow
   def initialize()
      super()
      setCaption(tr("サンプル"))
      @msg = QLabel.new(tr("タップした位置に座標を表示\nフィールドをタップしてからカーソルキー操作をしてみる"),self)
      @msg.setGeometry(0,0,640,100)

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

      connect(@fieldView.tapped, self, 'dispPos')
      connect(@fieldView.pressed, self, 'movePos')

      @text = QCanvasText.new(@field)

      catchEvent
   end

   def dispPos
      x = @fieldView.penPos.x
      y = @fieldView.penPos.y
      @text.move(x, y)
      @text.setText("X=#{x}, Y=#{y}")    # 座標から文字列作成
      @text.show
      @field.update                      # フィールド更新
   end

   def movePos 
      x = @text.x + @fieldView.movePos.x  # 現在の位置+移動量
      y = @text.y + @fieldView.movePos.y
      @text.move(x.to_i, y.to_i)
      @text.setText("X=#{x.to_i}, Y=#{y.to_i}")    # to_iは整数型にするため
      @text.show
      @field.update                      # フィールド更新
   end
end

class FieldView < QRCanvasView    # QCanvasViewではない
   def initialize(field, parent = nil, name = '')
      super(field, parent, name)
      @penPos = QPoint.new(0, 0)   #
      @movePos = QPoint.new(0, 0)  # 座標オブジェクト作成
      @tapped = RSignal.new        # 
      @pressed = RSignal.new       # 新規シグナル作成 

      setFocusPolicy( StrongFocus )   # これが無いとkeyPressEvent動作しない

      catchEvent
   end

   attr_reader :tapped   # 外部から読み取り可能にする
   attr_reader :penPos
   attr_reader :pressed
   attr_reader :movePos

   def keyPressEvent(e)  # カーソルキーの入力に応じた移動量を設定
      x = 0
      y = 0
#     p e.key         # keycode確認
      case e.key
         when Qt::Key_Up
             y = -10
         when Qt::Key_Down
             y = 10
         when Qt::Key_Left
             x = -10
         when Qt::Key_Right
             x = 10
      end
      @movePos.setX(x) # 移動量設定
      @movePos.setY(y)
      @pressed.send    # キープレスでシグナル送信
   end

   # QScrollViewのProtecedMember
   def contentsMousePressEvent(e)
      @penPos.setX(contentsX + e.x)     # contentsX が不明
      @penPos.setY(contentsY + e.y)
      @tapped.send                      # タップイベントでシグナル送信
   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