#java #javafx
#java #javafx
Вопрос:
Я новичок в JavaFX, и я создаю простую программу. Чего я пытаюсь добиться, так это создавать мяч каждые 5 секунд, который отскакивает от стен, и все шары должны двигаться каждые десятки раз в секунду (10 миллисекунд). Кроме того, не стесняйтесь оставлять другие предложения по моему коду.
Вот исходный код:
общедоступный класс Main расширяет приложение {
@Override
public void start(Stage stage) {
//Sets the title, adds a group, and background color
BorderPane canvas = new BorderPane();
Scene scene = new Scene(canvas, 640, 480, Color.WHITE);
Circle ball = new Circle(10, Color.RED);
ball.relocate(0, 10);
canvas.getChildren().add(ball);
stage.setTitle("Title");
stage.setScene(scene);
stage.show();
Timeline timeline = new Timeline(new KeyFrame(Duration.millis(20), new EventHandler<ActionEvent>() {
double dx = 5; //Step on x or velocity
double dy = 3; //Step on y
@Override
public void handle(ActionEvent t) {
//move the ball
ball.setLayoutX(ball.getLayoutX() dx);
ball.setLayoutY(ball.getLayoutY() dy);
Bounds bounds = canvas.getBoundsInLocal();
//If the ball reaches the left or right border make the step negative
if(ball.getLayoutX() <= (bounds.getMinX() ball.getRadius()) ||
ball.getLayoutX() >= (bounds.getMaxX() - ball.getRadius()) ){
dx = -dx;
}
//If the ball reaches the bottom or top border make the step negative
if((ball.getLayoutY() >= (bounds.getMaxY() - ball.getRadius())) ||
(ball.getLayoutY() <= (bounds.getMinY() ball.getRadius()))){
dy = -dy;
}
}
}));
timeline.setCycleCount(Timeline.INDEFINITE);
timeline.play();
}
public static void main(String[] args) {
launch(args);
}
}
Комментарии:
1. Подсказка: ведите список шаров, а затем просматривайте этот список, чтобы обновить положение каждого шара. Используйте таймер / поток для создания новых шаров и добавления их в список, чтобы их можно было обновлять.
Ответ №1:
Вот один из способов сделать это, как предложено в комментариях:
- Создайте пользовательский объект, содержащий шар и информацию о его ориентации.
- Добавьте вновь созданный объект в список и шар в холст.
- Перебирайте все шары и размещайте их на основе информации об их ориентации.
- По достижении желаемого времени добавьте новый шар.
Для простоты вам не нужны какие-либо сопутствующие материалы. Возможно, их использование улучшит реализацию (но я сейчас не касаюсь этого). 🙂
Вот демонстрация использования пунктов, о которых я упоминал.
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.geometry.Bounds;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
import javafx.util.Duration;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.List;
public class CanvasBallCreation_Demo extends Application {
List<Ball> balls = new ArrayList<>();
BorderPane canvas;
double dx = 5; //Step on x or velocity
double dy = 3; //Step on y
double refresh = 20;//ms
double addBallDuration = 5000;//ms
double temp = 0;
SecureRandom rnd = new SecureRandom();
@Override
public void start(Stage stage) {
canvas = new BorderPane();
Scene scene = new Scene(canvas, 640, 480, Color.WHITE);
addBall();
stage.setTitle("Title");
stage.setScene(scene);
stage.show();
Timeline timeline = new Timeline(new KeyFrame(Duration.millis(refresh), e->moveBalls()));
timeline.setCycleCount(Timeline.INDEFINITE);
timeline.play();
}
private void addBall(){
Ball ball = new Ball();
balls.add(ball);
canvas.getChildren().add(ball.getBall());
}
private void moveBalls() {
temp = temp refresh;
if(temp>addBallDuration){
temp = 0;
addBall();
}
Bounds bounds = canvas.getBoundsInLocal();
balls.forEach(obj -> {
Circle ball = obj.getBall();
double tx = obj.getTx();
double ty = obj.getTy();
ball.setLayoutX(ball.getLayoutX() dx*tx);
ball.setLayoutY(ball.getLayoutY() dy*ty);
//If the ball reaches the left or right border make the step negative
if (ball.getLayoutX() <= (bounds.getMinX() ball.getRadius()) ||
ball.getLayoutX() >= (bounds.getMaxX() - ball.getRadius())) {
obj.setTx(-tx);
}
//If the ball reaches the bottom or top border make the step negative
if ((ball.getLayoutY() >= (bounds.getMaxY() - ball.getRadius())) ||
(ball.getLayoutY() <= (bounds.getMinY() ball.getRadius()))) {
obj.setTy(-ty);
}
});
}
class Ball {
Circle ball = new Circle(10, Color.RED);
double tx = 1;
double ty = 1;
public Ball(){
// Placing the ball at a random location between 0,0 and 10,10 to generate random paths
ball.relocate(rnd.nextInt(10), rnd.nextInt(10));
}
public Circle getBall() {
return ball;
}
public double getTx() {
return tx;
}
public void setTx(double tx) {
this.tx = tx;
}
public double getTy() {
return ty;
}
public void setTy(double ty) {
this.ty = ty;
}
}
}
Ответ №2:
Есть несколько вариантов, java.util.concurrent.TimeUnit
или Thread.sleep
.
Возможно, вы захотите рассмотреть оба варианта, и если вам нужно выполнить две операции одновременно (создание новых шаров, перемещение шаров) Я бы подумал о том, чтобы использовать новую нить для каждого шарика.
Вы можете прочитать больше об использовании потоков, используя эти статьи, и ваша простая программа на самом деле кажется отличным вариантом использования для изучения их.
https://www.geeksforgeeks.org/multithreading-in-java/
https://www.tutorialspoint.com/java/java_multithreading.htm
https://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html
Комментарии:
1.Потоки работают,
JavaFX
но, вероятно, являются самым сложным маршрутом. Первый вариант, на который следует обратитьJavaFX
внимание, — это что-то изAnimation
API
. Второй вариант должен быть таким.