質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.55%

JavaFXで複数のキーイベントを同時に受け取るにはどうしたらいいでしょうか?

受付中

回答 1

投稿

  • 評価
  • クリップ 1
  • VIEW 3,626

nuiri1343

score 52

前提・実現したいこと

javafxで、キーイベントを同時に複数受け取りたい。

該当のソースコード

AnchorPane root = new AnchorPane();
root.setOnKeyPressed(event -> moveImage(event));
public void moveImage(KeyEvent event){
 if(event.getCode()==KeyCode.UP){}
 if(event.getCode()==KeyCode.DOWN){}
 if(event.getCode()==KeyCode.RIGHT){}
 if(event.getCode()==KeyCode.LEFT){}
}

試したこと+やりたいこと

上記のソースコードのようにして、キーイベントを受け取り、
矢印キーの上なら画像を少し上に動かし、下なら下に動かし、右なら右に、左なら左に
という風にはできましたが、
これにプラスして、右と上を同時に押したら斜め右上に動かし、左と下なら斜め左下に・・・
という風に、8方向に動かしたいです。
さらに加えて、もしSHIFTが同時に押されていたら動かす量を増やすといったようにしたいのですが、
上記のソースコードだとKeyEventを一つしか受け取ってくれないのです。
どうしたらいいでしょうか?

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

+1

おそらくキーを押している間移動したいものを作りたいのでしょうが、いまの構造では無理があります。

とりあえずヒント的な回答を書いておきます。

  • いまのsetOnKeyPressedだけでは「押しっぱなし」を検知できません。setOnKeyReleasedも使う必要があります。
  • boolean型の変数up,down,left,right,shiftを用意し、setOnKeyPressedで各キーに対応したフラグをtrueにし、setOnKeyReleasedでfalseにします
  • 別スレッドで移動計算を行います。
  • Platform.runLaterを使い、コントロールの座標を計算結果に合わせて移動させます

キー管理クラスのサンプル

なにもテストしてませんので動作は保証しかねますが、やろうとすることはこういうことだと思います。

public class KeyManager {
    private Map<KeyCode, boolean> map = new HashMap<>();
    public void handleEvent(KeyEvent e) {
        switch(e.getEventType()) {
        case KeyEvent.KEY_PRESSED:
            map.put(e.getCode(), false);
            break;
        case KeyEvent.KEY_RELEASED:
            map.put(e.getCode(), true);
            break;
        }
    }
    public boolean isPressed(KeyCode code) {
        return map.containsKey(code)?map.get(code):false;
    }
}


これをsetOnKeyPressed、setOnKeyReleasedそれぞれでKeyManager#handleEventを呼んでやり、Timeline内でisPressed(KeyCode.UP) & isPressed(KeyCode.LEFT)としてやれば「左上」を押していると認識できます。ただし、よくある問題としてフォーカスが外れたときに押しっぱなしになったりするので、そのへんの対処は自分で考えてみてください。

public static KeyManager keyManager = new KeyManager;

// 中略
root.setOnKeyPressed(event -> keyManager.handleEvent(event));
root.setOnKeyReleased(event -> keyManager.handleEvent(event));

// Timelineの処理の中
if(keyManager.isPressed(KeyCode.UP)) {
    //上を押されている
}
if(keyManager.isPressed(KeyCode.LEFT)) {
    //左を押されている
}

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/06/25 15:23

    コレクションには代表的な構造に「Array」「Map」などがあります。
    Arrayは普通の配列と一緒で0番目から始まる、「要素に順番のある」コレクションです。
    Mapは連想配列と言われるもので、map[りんご]=赤、map[バナナ]=黃、のように、「添字に数字ではないもの」を使うことのできる配列です。
    そして、Array、Mapともにクラスではなくインタフェースで、実体は持ちません。あくまで「そういった機能」を表すものです。
    インタフェースはわかりますか?インタフェースは言ってみれば「規格」のようなもので、「規格」に沿ったものであれば同じもののように扱える、というものです。例えばUSBのマウスとキーボードがあると思いますが、差込口は同じ形ですよね?あれはお互い規格に沿った作りをしているから同じ差込口に刺すことができます。それと同じように、Mapというインタフェースの規格に沿うものであれば、中身がどうなっているかは気にする必要なく扱うことができるわけです。
    Mapはput(連想配列への代入)、get(連想配列からの参照)のメソッドを持ちます。HashMapは連想配列のキーとしてObject#hashCode()を使って管理する実装になっています。
    なので、キーに文字列を使うときによく使います。KeyCodeもhashCodeがちゃんとついているのでHashMapのキーとして扱うことができるわけです。

    キャンセル

  • 2016/06/25 16:49

    map.containsKey
    これは自作メソッドではないのですか?

    キャンセル

  • 2016/06/25 17:38

    それもMapインタフェースが持つメソッドの一つです。containsKeyは、「すでにそのキーが配列に使われているか」を問い合わせるメソッドです。ここに使い方が載っています。
    http://docs.oracle.com/javase/jp/7/api/java/util/Map.html

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.55%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる