2017-03-22 37 views
0

我正在开发一个使用JavaFX的简单Pong克隆,并且我在移动桨时遇到了困难。我想为此使用KeyEventDispatcher,并在我的AnimationTimer循环中检查按键。调用dispatchKeyEvent来执行形状翻译

Main类:

public class Main extends Application { 

    private Player m_pUser; 

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

     Group root = new Group(); 
     Scene scene = new Scene(root, 500, 300); 
     ObservableList list = root.getChildren(); 

     KeyPressedChecker kpc = new KeyPressedChecker(); 

     m_pUser = new Player(kpc); 

     list.add(m_pUser.getPaddleDrawable()); 

     GamePlayLoop gameLoop = new GamePlayLoop(m_pUser); 
     gameLoop.start(); 

     primaryStage.setScene(scene); 
     primaryStage.show(); 
    } 

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

GamePlayLoop类:

public class GamePlayLoop extends AnimationTimer { 

    Player m_pUser; 

    public GamePlayLoop(Player p) { 
     m_pUser = p; 
    } 

    public void handle(long now) { 
     m_pUser.update(); 
    } 
} 

KeyPressedChecker类:

public class KeyPressedChecker implements KeyEventDispatcher { 

    private static boolean downPressed = false; 

    @Override 
    public boolean dispatchKeyEvent(KeyEvent ke) { 
     synchronized (KeyPressedChecker.class) { 
      switch (ke.getID()) { 

       case KeyEvent.KEY_PRESSED: 
        if (ke.getKeyCode() == KeyEvent.VK_DOWN) 
         downPressed = true; 
       break; 
       case KeyEvent.KEY_RELEASED: 
        if (ke.getKeyCode() == KeyEvent.VK_DOWN) 
         downPressed = false; 
        break; 
      } 

      return false; 
     } 
    } 

    public static boolean isDownPressed() { 
     synchronized (KeyPressedChecker.class) { 
      return downPressed; 
     } 
    } 
} 

Player类:

public class Player { 

    private Paddle m_paddle; 
    private KeyPressedChecker m_kpc; 

    public Player(KeyPressedChecker kpc) { 
     m_paddle = new Paddle(); 
    } 

    public Rectangle getPaddleDrawable() { 
     return m_paddle.getDrawable(); 
    } 

    public void update() { 
     if (m_kpc.isDownPressed()) 
      m_paddle.moveDown(); 
     m_paddle.update(); 
    } 
} 

最后我Paddle类:

public class Paddle { 

    private Rectangle m_rect; 
    private double m_nPosY; 

    public Paddle() { 
     m_rect = new Rectangle(10, 60); 
    } 

    public void moveDown() { 
     m_nPosY += 5; 
    } 

    public Rectangle getDrawable() { 
     return m_rect; 
    } 

    public void update() { 
     m_rect.setTranslateY(m_nPosY); 
    } 
} 

我的问题是,桨不在现场翻译。实际上,dispatchKeyEvent根本不被调用。为什么是这样?

回答

0

KeyEventDispatcher是AWT的一部分,AWT是一个完全独立于JavaFX的工具包。 (即使它是JavaFX的一部分,你只是实例化你的实现类,但不要对它做任何事情......)。

在JavaFX中执行此操作的方法是在场景中为KeyEvent.KEY_PRESSED事件注册事件处理程序。

因此,使用当前的设计(约),你会做

public class KeyPressedChecker implements EventHandler<KeyEvent> { 

    private boolean downPressed = false; 

    @Override 
    public void handle(KeyEvent ke) { 
     if (ke.getEventType() == KeyEvent.KEY_PRESSED) { 
      downPressed = true ; 
     } else if (ke.getEventType() == KeyEvent.KEY_RELEASED) { 
      downPressed = false ; 
     } 
    } 

    public boolean isDownPressed() { 
     return downPressed; 
    } 

} 

在你Player类(我改名领域,以配合适当的naming conventions

public class Player { 

    private Paddle paddle; 
    private KeyPressedChecker kpc; 

    public Player(KeyPressedChecker kpc) { 
     this.paddle = new Paddle(); 
     this.kpc = kpc ; 
    } 

    public Rectangle getPaddleDrawable() { 
     return paddle.getDrawable(); 
    } 

    public void update() { 
     if (kpc.isDownPressed()) 
      paddle.moveDown(); 
     paddle.update(); 
    } 
} 

,然后一切都与

相连
public class Main extends Application { 

    private Player pUser; 

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

     Group root = new Group(); 
     Scene scene = new Scene(root, 500, 300); 
     ObservableList list = root.getChildren(); 

     KeyPressedChecker kpc = new KeyPressedChecker(); 

     scene.addEventHandler(KeyEvent.ANY, kpc); 

     pUser = new Player(kpc); 

     list.add(pUser.getPaddleDrawable()); 

     GamePlayLoop gameLoop = new GamePlayLoop(pUser); 
     gameLoop.start(); 

     primaryStage.setScene(scene); 
     primaryStage.show(); 
    } 

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

这是非常有用的,解决了我的问题,谢谢你很多!我知道重命名类变量 - 我为它们命名的推理例如'm_pUser'是表示一个成员变量(与匈牙利符号结合)以避免必须确保我写'this'以避免名称冲突,因为局部变量不会在名称中包含'm'。希望我正确解释自己。 – petehallw

+0

@petehallw我理解其他语言中使用的约定,但强烈建议您在编写Java时遵循Java约定(对其他语言也是如此)。这会让其他程序员更容易阅读你的代码。就FWIW而言,我讨厌'm_pUser',因为它不可能在内部发声。 (如果能解决问题,请将答案标为正确。) –

+0

可以理解,我会在将来考虑。标记为正确,谢谢。出于兴趣,你的意思是“内部发声”? – petehallw