'JavaFX how to use AnimationTimer in separate class?
I've seen many examples that write AnimationTimer and KeyListener in Main class but not seen in another class.
I've tried How to write a KeyListener for JavaFX in "VolleyController", but I don't know why it did not work.
First, I used KeyEvent to move the image just like the first code. The third code is my Main class. I want to rewrite the methods to move images just like the second code.
But I went into some error written in the second code. How can I deal with it?
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.scene.image.ImageView;
import javafx.scene.input.KeyEvent;
public class VolleyController implements EventHandler<KeyEvent> {
double pika1LocationY = 556;
double pika2LocationY = 556;
double pika1LocationX = 0;
double pika2LocationX = 1050;
boolean pika2MoveLeft = false;
boolean pika2MoveRight = false;
boolean pika1MoveLeft = false;
boolean pika1MoveRight = false;
@FXML
ImageView pika1,pika2,ball;
@Override
public void handle(KeyEvent e) {
switch (e.getCode()) {
case ESCAPE:
Main.currentStage.setScene(Main.menuScene);
break;
case UP:
break;
case LEFT:
pika2MoveLeft = true;
break;
case RIGHT:
pika2MoveRight = true;
break;
case T:
break;
case F:
pika1MoveLeft = true;
break;
case H:
pika1MoveRight = true;
break;
}
move();
}
public void released(KeyEvent r) {
switch (r.getCode()) {
case LEFT:
pika2MoveLeft = false;
break;
case RIGHT:
pika2MoveRight = false;
break;
case F:
pika1MoveLeft = false;
break;
case H:
pika1MoveRight = false;
break;
}
}
public void move() {
if(pika1MoveLeft && pika1.getLayoutX()>=0)
pika1.setLayoutX(pika1.getLayoutX()-10);
if(pika1MoveRight && pika1.getLayoutX()<=440 )
pika1.setLayoutX(pika1.getLayoutX()+10);
if(pika2MoveLeft && pika2.getLayoutX()>600)
pika2.setLayoutX(pika2.getLayoutX()-10);
if(pika2MoveRight && pika2.getLayoutX()<1050)
pika2.setLayoutX(pika2.getLayoutX()+10);
}
}
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.scene.image.ImageView;
import javafx.scene.input.KeyEvent;
public class VolleyController implements EventHandler<KeyEvent> {
double pika1LocationY = 556;
double pika2LocationY = 556;
double pika1LocationX = 0;
double pika2LocationX = 1050;
boolean pika2MoveLeft = false;
boolean pika2MoveRight = false;
boolean pika1MoveLeft = false;
boolean pika1MoveRight = false;
@FXML
ImageView pika1,pika2,ball;
//this gives me a syntax error about getScene(), but the following did not
Main.currentStage.getScene().setOnKeyPressed(new EventHandler<KeyEvent>() {
@Override
public void handle(KeyEvent e) {
switch (e.getCode()) {
case ESCAPE:
Main.currentStage.setScene(Main.menuScene);
break;
case UP:
break;
case LEFT:
pika2MoveLeft = true;
break;
case RIGHT:
pika2MoveRight = true;
break;
case T:
break;
case F:
pika1MoveLeft = true;
break;
case H:
pika1MoveRight = true;
break;
}
}}); //this told me to delete tokens
//this did not give me a syntax error
Main.currentStage.getScene().setOnKeyReleased(new EventHandler<KeyEvent>() {
@Override
public void handle(KeyEvent r) {
switch (r.getCode()) {
case LEFT:
pika2MoveLeft = false;
break;
case RIGHT:
pika2MoveRight = false;
break;
case F:
pika1MoveLeft = false;
break;
case H:
pika1MoveRight = false;
break;
}
}
});
AnimationTimer timer=new AnimationTimer() {
@Override
public void handle(long now)
{
int pika1dx=0, pika2dx=0;
if(pika1MoveLeft) pika1dx-=10;
if(pika1MoveRight) pika1dx+=10;
if(pika2MoveLeft) pika2dx-=10;
if(pika2MoveLeft) pika2dx-=10;
PikaMoveBy(pika1dx,pika2dx);
}
};
timer.start();
}
public void PikaMoveBy(int pika1dx,int pika2dx)
{
if(pika1dx==0 || pika2dx==0) return;
final double pika1cx=pika1.getBoundsInLocal().getWidth()/2;
final double pika2cx=pika2.getBoundsInLocal().getWidth()/2;
double pika1x=pika1cx+pika1.getLayoutX()+pika1dx;
double pika2x=pika2cx+pika2.getLayoutX()+pika2dx;
PikaMoveTo(pika1x, pika2x);
}
public void PikaMoveTo(double pika1x, double pika2x)
{
final double pika1cx=pika1.getBoundsInLocal().getWidth()/2;
final double pika2cx=pika2.getBoundsInLocal().getWidth()/2;
if(pika1x-pika1cx>=0 && pika1x+pika1cx<450 && pika2x-pika2cx>600 && pika2x+pika2cx<1050)
{
pika1.relocate(pika1x-pika1cx, pika1_lct_y);
pika2.relocate(pika2x-pika2cx, pika2_lct_y);
}
}
import java.net.URL;
import java.util.ResourceBundle;
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.image.ImageView;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
public class Main extends Application {
public static Stage currentStage;
public static Scene menuScene;
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) throws Exception {
currentStage=primaryStage;
Parent root=FXMLLoader.load(getClass().getResource("Menu.fxml"));
Scene MenuScene = new Scene(root);
currentStage.setScene(MenuScene); //use setScene() to switch the scene
currentStage.setTitle("PikaVolley");
currentStage.show();
}
}
Solution 1:[1]
To get key handlres and AnimationTimer working use a simple FXML (Volley.fxml):
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.Pane?>
<?import javafx.scene.layout.VBox?>
<VBox spacing="10.0" xmlns="http://javafx.com/javafx/10.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="test.VolleyController">
<children>
<Label alignment="CENTER" contentDisplay="CENTER" prefHeight="17.0" prefWidth="248.0" text="Press Start.Use Arows to set direction" />
<Pane prefHeight="250.0" prefWidth="250.0">
<children>
<ImageView fx:id="ball" fitHeight="50.0" fitWidth="50.0" pickOnBounds="true" preserveRatio="true" />
</children>
</Pane>
<Button fx:id="startBtn" mnemonicParsing="false" onAction="#start" text="Start" />
</children>
</VBox>
And its controller (see comments):
import javafx.animation.AnimationTimer;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.KeyEvent;
public class VolleyController implements EventHandler<KeyEvent> {
//always use publicly available resources when posting
private static final String BALL = "https://cdn3.iconfinder.com/data/icons/softwaredemo/PNG/32x32/Circle_Red.png";
boolean moveRight = false, moveLeft = false, moveUp = false, moveDown = false;
private static final int DX = 1, DY = 1;
@FXML
ImageView ball;
@FXML
Button startBtn;
@FXML
void initialize(){
ball.setImage(new Image(BALL)); //initialize image view
}
@FXML
void start(){
ball.getScene().setOnKeyPressed(this); //add Key press and release handlers to scene
ball.getScene().setOnKeyReleased(this);
//construct and invoke AnimationTimer
AnimationTimer timer = new AnimationTimer(){
@Override
public void handle(long now) {
move(); //repeatedly invoke move
}
};
timer.start();
startBtn.setDisable(true);
}
@Override
public void handle(KeyEvent e) {
moveRight = false; moveLeft = false; moveUp = false; moveDown = false;
//change movement directions based on key events
switch (e.getCode()) {
case UP:
moveUp = true;
break;
case LEFT:
moveLeft = true;
break;
case RIGHT:
moveRight = true;
break;
case DOWN:
moveDown = true;
break;
}
}
//move if any of the direction control booleans is true
private void move() {
if(moveLeft) {
ball.setLayoutX(ball.getLayoutX()-DX);
}else if(moveRight) {
ball.setLayoutX(ball.getLayoutX()+DX);
}else if(moveDown) {
ball.setLayoutY(ball.getLayoutY()+DY);
}else if(moveUp) {
ball.setLayoutY(ball.getLayoutY()-DY);
}
}
}
test it using :
public class Main extends Application {
@Override
public void start(Stage currentStage) throws Exception {
Parent root=FXMLLoader.load(getClass().getResource("Volley.fxml"));
currentStage.setScene(new Scene(root));
currentStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
