首页 > 解决方案 > JavaFX - 生成形状并用箭头移动它们

问题描述

我正在编写一个 JavaFX 代码,每次用户按下按钮时都会生成 4 个不同的形状(圆形、矩形、线条、椭圆),到目前为止,我已经完成了圆形和矩形,形状生成得很好,但问题是,当我按下按钮时,我无法移动形状,即使在我添加按钮之前它已经很好地移动了它们,但我无法弄清楚代码有什么问题。

这是代码:

package sample;

import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Ellipse;
import javafx.scene.shape.Line;
import javafx.stage.Stage;
import javafx.scene.control.Button;
import javafx.scene.shape.Rectangle;
import javafx.geometry.Insets;
import java.util.Random;


public class Main extends Application {
Pane pane;
Circle circle;
Rectangle rectangle;
    @Override
    public void start(Stage primaryStage) {
        pane = new Pane();
        Button button = new Button("Generate");
        CreateRect c = new CreateRect();
        button.setOnAction(c);
        pane.setPadding(new Insets(30, 30, 30, 30));
        circle = new Circle(30, 30, 30);
        rectangle = new Rectangle(30,30,50,20);
        pane.getChildren().add(button);
        pane.setOnKeyPressed(e -> {
            switch (e.getCode()) {
                case UP : circle.setCenterY(circle.getCenterY() >
                        circle.getRadius() ? circle.getCenterY() - 15 :
                        circle.getCenterY()); break;
                case DOWN : circle.setCenterY(circle.getCenterY() <
                        pane.getHeight() - circle.getRadius() ?
                        circle.getCenterY() + 15 : circle.getCenterY());
                    break;
                case LEFT : circle.setCenterX(circle.getCenterX() >
                        circle.getRadius() ? circle.getCenterX() - 15 :
                        circle.getCenterX()); break;
                case RIGHT : circle.setCenterX(circle.getCenterX() <
                        pane.getWidth() - circle.getRadius() ?
                        circle.getCenterX() + 15: circle.getCenterX());
            }
        });

        Scene scene = new Scene(pane, 500, 300);
        primaryStage.setTitle("SHAPES");
        primaryStage.setScene(scene);
        primaryStage.show();
        pane.requestFocus();
    }

private class CreateRect implements EventHandler<ActionEvent> {

    @Override
    public void handle(ActionEvent e) {
        double s;
        Random generator = new Random();
        s = generator.nextDouble();
        pane.getChildren().remove(rectangle);
        pane.getChildren().remove(circle);
        if (s < 0.5) {
            pane.getChildren().add(rectangle);
            rectangle.setX(100);
            rectangle.setY(100);
            rectangle.setWidth(50);
            rectangle.setHeight(20);
            rectangle.setFill(Color.RED);
        } else {
            pane.getChildren().add(circle);
            circle.setCenterX(100);
            circle.setCenterY(100);
            circle.setRadius(80);
            circle.setFill(Color.RED);
        }
    }
}

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

标签: javajavafx

解决方案


问题是按钮在您按下后会保留键盘焦点,并消耗按键事件。一种解决方案是通过将焦点传递给您创建的形状来放弃焦点:

private class CreateRect implements EventHandler<ActionEvent> {

    @Override
    public void handle(ActionEvent e) {
        double s;
        Random generator = new Random();
        s = generator.nextDouble();
        pane.getChildren().remove(rectangle);
        pane.getChildren().remove(circle);
        if (s < 0.5) {
            pane.getChildren().add(rectangle);
            rectangle.setX(100);
            rectangle.setY(100);
            rectangle.setWidth(50);
            rectangle.setHeight(20);
            rectangle.setFill(Color.RED);
            rectangle.requestFocus();
        } else {
            pane.getChildren().add(circle);
            circle.setCenterX(100);
            circle.setCenterY(100);
            circle.setRadius(80);
            circle.setFill(Color.RED);
            circle.requestFocus();
        }
    }
}

如果您特别希望按钮保持焦点(因此它响应其通常的键事件,例如从 生成动作SPACE,您可以使用不同的键事件。但这似乎是一个不太健壮的解决方案(依赖于内部事件处理按钮):

    pane.setOnKeyReleased(e -> {
        // ...
    });

推荐阅读