Home > other >  JavaFX - Generating shapes and moving them with arrows
JavaFX - Generating shapes and moving them with arrows

Time:09-22

I'm working on a JavaFX code which generates 4 different shapes (circle,rectangle,line,ellipse) each time the user presses the button , so far I've done the circle and the rectangle , the shapes are getting generated very well , but the problem is that when I press the button I can't move the shapes , even though it moved them very well before I added the button , I can't figure out what's wrong with the code.

Here is the CODE :

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);
}
}

CodePudding user response:

The problem is that the button retains keyboard focus after you press it, and consumes the key events. One solution is to relinquish focus by passing it to, for example, the shape you create:

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();
        }
    }
}

If you specifically want the button to retain focus (so it responds to its usual key events, such as generating an action from SPACE, you can use a different key event. This seems a less robust solution though (relying on the internal event handling of the button):

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

CodePudding user response:

your code for

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());
        }

is only for the circle so you have to take care in your code for other shapes

for example:

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());
            break;
    }
        switch (e.getCode()) {
            case UP : rectangle.setY(rectangle.getY()-15);
                break;
            case DOWN : rectangle.setY(rectangle.getY() 15);
                break;
            case LEFT : rectangle.setX(rectangle.getX()-15);
                break;
            case RIGHT : rectangle.setX(rectangle.getX() 15);
                break;
        }
});

(better do with more OOP method)

  • Related