【问题标题】:JavaFX - Generating shapes and moving them with arrowsJavaFX - 生成形状并用箭头移动它们
【发布时间】:2021-09-22 11:22:33
【问题描述】:

我正在编写一个 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);
}
}

【问题讨论】:

    标签: java javafx


    【解决方案1】:

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

    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 -> {
            // ...
        });
    

    【讨论】:

      【解决方案2】:

      你的代码

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

      仅适用于circle,因此您必须注意其他形状的代码

      例如:

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

      (最好用更多的OOP方法)

      【讨论】:

      • 是的,我知道这一点,我的问题是当我按下按钮时,即使是圆圈也没有移动。所以基本上按下按钮后什么都不能移动
      • 在我的电脑上它确实移动了,我使用 Java 8,所以这可能会有所作为......
      【解决方案3】:

      如果您将事件处理程序视为触发操作的触发器,则更容易概念化。然后你可以更容易地分解事情。因此,我已将您的 EventHandler 类转换为一个简单的方法,并从 lambda 调用它,这也将焦点重置回窗格:

      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");
              button.setOnAction(evt -> {
                  createShape();
                  pane.requestFocus();
              });
              pane.setPadding(new Insets(30, 30, 30, 30));
              circle = new Circle(30, 30, 30);
              rectangle = new Rectangle(30, 30, 50, 20);
              pane.getChildren().addAll(button, circle);
              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();
          }
      
          public void createShape() {
              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);
          }
      }
      

      应该可以。不过,萨雷尔关于具有特定形状运动的理论是完全正确的。我会用 setTranslateX() 和 setTranslateY() 移动形状。

      【讨论】:

        猜你喜欢
        • 2020-10-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多