2016-05-26 23 views
3

JavaFXで単一のキー押下を検出する問題があります。私は矢印キーを検出する必要がありますが、私はそれらのキーのいずれかを押すたびに、コードの一部が複数回呼び出されています。 AnimationTimer()がループなので、これが理由ですが、私は単一のキータップを検出する方法がわかりません。私は(同じコースの他のキーとなる)矢印ボタンを押しするとJavaFXで単一キーの押下を検出します

import javafx.animation.AnimationTimer; 
import javafx.application.Application; 
import javafx.event.EventHandler; 
import javafx.scene.Group; 
import javafx.scene.Scene; 
import javafx.scene.canvas.Canvas; 
import javafx.scene.canvas.GraphicsContext; 
import javafx.scene.input.KeyEvent; 
import javafx.scene.paint.Color; 
import javafx.stage.Stage; 

import java.util.HashSet; 

public class Main extends Application { 

    Stage window; 
    static Scene scene; 

    private static char[][] mapa = { 
      {'X','X','X','X','X'}, 
      {'X','.','.','.','X'}, 
      {'X','.','M','.','X'}, 
      {'X','.','.','.','X'}, 
      {'X','X','X','X','X'} 
    }; 

    private final int sizeX = 16; 
    private final int sizeY = 16; 

    static HashSet<String> currentlyActiveKeys; 

    @Override 
    public void start(Stage primaryStage) throws Exception { 

     window = primaryStage; 
     window.setTitle("Hello World"); 

     Group root = new Group(); 
     scene = new Scene(root); 

     window.setScene(scene); 

     Canvas canvas = new Canvas(512 - 64, 256); 
     root.getChildren().add(canvas); 

     prepareActionHandlers(); 

     GraphicsContext gc = canvas.getGraphicsContext2D(); 

     new AnimationTimer() { 
      @Override 
      public void handle(long now) { 
       gc.clearRect(0,0,512,512); 

       for(int i = 0; i < mapa.length; i++) { 
        for(int j = 0; j < mapa[i].length; j++) { 
         if(mapa[i][j] == 'X') { 
          gc.setLineWidth(5); 
          gc.setFill(Color.RED); 
          gc.fillRect(sizeX + i*sizeX, sizeY + j*sizeY, sizeX, sizeY); 
         } else if(mapa[i][j] == '.') { 
          gc.setLineWidth(5); 
          gc.setFill(Color.GREEN); 
          gc.fillRect(sizeX + i*sizeX, sizeY + j*sizeY, sizeX, sizeY); 
         } else if(mapa[i][j] == 'M') { 
          gc.setLineWidth(5); 
          gc.setFill(Color.BLACK); 
          gc.fillRect(sizeX + i*sizeX, sizeY + j*sizeY, sizeX, sizeY); 
         } 
        } 
       } 

       if(currentlyActiveKeys.contains("LEFT")) { 
        System.out.println("left"); 
       } 

       if(currentlyActiveKeys.contains("RIGHT")) { 
        System.out.println("right"); 
       } 

       if(currentlyActiveKeys.contains("UP")) { 
        System.out.println("up"); 
       } 

       if(currentlyActiveKeys.contains("DOWN")) { 
        System.out.println("down"); 
       } 
      } 
     }.start(); 

     window.show(); 
    } 

    private static void prepareActionHandlers() 
    { 
     currentlyActiveKeys = new HashSet<String>(); 
     scene.setOnKeyPressed(new EventHandler<KeyEvent>() { 
      @Override 
      public void handle(KeyEvent event) 
      { 
       currentlyActiveKeys.add(event.getCode().toString()); 

      } 
     }); 
     scene.setOnKeyReleased(new EventHandler<KeyEvent>() { 
      @Override 
      public void handle(KeyEvent event) 
      { 
       currentlyActiveKeys.remove(event.getCode().toString()); 

      } 
     }); 
    } 

    public static void main(String[] args) { 
     launch(args); 
    } 
} 

、スコープに、私は同じような結果を得ています::とにかく、ここにコードがある

down 
down 
down 
down 
down 
down 

これは明らかとして起こります私がボタンを押すと長く。押さなくなると印刷が終了します。私が達成したいのは、いったんボタンを押しても(どれくらい長く押さえても)、私はdownを1回だけ得ることです。 canvasの四角形の色を更新したいので、これが必要です。

+0

この【関連する質問(http://stackoverflow.com/questions/29962395/how-to-write-a-keylistener-for-javafx)を助けることができる(またはではないかもしれない)。私の推測では、あなたは何か別のことをしようとしているということです。 – jewelsea

+0

@jewelsea私はコードを編集していたし、間違ったバージョンを貼り付けていた。今すぐ 'setOnKeyPressed'があります。 – Lisek

+0

@jewelsea矢を押すと主人公が動いていきます。私の例では、キーを押したままでも、一歩も進めるために英雄になりたいと思います。それは動作しません。ボタンを押したときに、私は複数のプリントを取得しています。 – Lisek

答えて

1

は、あなたがダウンキーを押し続けたときに、それはあなたが本当により多くのキーを押していなくても、キープレスイベントを生成し続けるよう、OSが自動入力機能の種類を持っているということです一度。

キー押下ハンドラとキーリリースハンドラの両方を追加し、各キーにブール状態を追加することで、押されてからキーを処理したかどうかを追跡できます。キーが離されるたびに、処理された状態をリセットして、次に実際に押されたときに処理できるようにします。

サンプルアプリケーション

import javafx.animation.AnimationTimer; 
import javafx.application.Application; 
import javafx.scene.Group; 
import javafx.scene.Scene; 
import javafx.stage.Stage; 

import java.util.HashMap; 

public class Main extends Application { 
    private HashMap<String, Boolean> currentlyActiveKeys = new HashMap<>(); 

    @Override 
    public void start(Stage stage) throws Exception { 
     final Scene scene = new Scene(new Group(), 100, 100); 
     stage.setScene(scene); 

     scene.setOnKeyPressed(event -> { 
      String codeString = event.getCode().toString(); 
      if (!currentlyActiveKeys.containsKey(codeString)) { 
       currentlyActiveKeys.put(codeString, true); 
      } 
     }); 
     scene.setOnKeyReleased(event -> 
      currentlyActiveKeys.remove(event.getCode().toString()) 
     ); 

     new AnimationTimer() { 
      @Override 
      public void handle(long now) { 
       if (removeActiveKey("LEFT")) { 
        System.out.println("left"); 
       } 

       if (removeActiveKey("RIGHT")) { 
        System.out.println("right"); 
       } 

       if (removeActiveKey("UP")) { 
        System.out.println("up"); 
       } 

       if (removeActiveKey("DOWN")) { 
        System.out.println("down"); 
       } 
      } 
     }.start(); 

     stage.show(); 
    } 

    private boolean removeActiveKey(String codeString) { 
     Boolean isActive = currentlyActiveKeys.get(codeString); 

     if (isActive != null && isActive) { 
      currentlyActiveKeys.put(codeString, false); 
      return true; 
     } else { 
      return false; 
     } 
    } 

    public static void main(String[] args) { 
     launch(args); 
    } 
} 
0

グローバルブール値を宣言して、press =!pressのようにtoogleを宣言できます。その後、2秒ごとにそれを真に戻すか、またはその効果を何かに戻す。何が起こっている

if(currentlyActiveKeys.contains("DOWN") && press) { 
     press = !press;//sets it false 
     System.out.println("down"); 
} 
+0

プレスを' true'に戻すにはどうすればよいか分かりません。 'setOnKeyReleased'でそれを行うと、' AnimationTimer() 'がリフレッシュしている間にキーを保持しているので、もう一度この問題が発生します。 – Lisek

+0

setOnKeyReleasedメソッドでfalseを押すように設定されていますか?キーを1回だけ押すことができ、リリースまでリセットされません。 – Aaron

+0

はい。これは明らかですが、私は 'press'を' true'に戻すためにどのように設定しますか? – Lisek

関連する問題