在javafx中尝试用一个按钮使一个4色的圆旋转

icnyk63a  于 2023-06-28  发布在  Java
关注(0)|答案(3)|浏览(92)

我试图创建一个显示四种颜色的圆圈,其中轮子的每个四分之一都有不同的颜色,并且有一个按钮,用于在按下时将轮子的颜色向右旋转90度。
这是我目前为止的代码。我有按钮和圆圈显示了罚款,但不能让它旋转时,按下按钮。

import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.layout.FlowPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Arc;
import javafx.scene.shape.ArcType;
import javafx.stage.Stage;
import javafx.event.ActionEvent;
import javafx.geometry.Pos;
import javafx.scene.control.Button;
import java.util.concurrent.TimeUnit;

public class four_color_wheel extends Application {
    private Group circle;
    private FlowPane pane;
    private Button rotate;
    private Arc blueArc, greenArc, yellowArc, redArc;


    public void start(Stage primaryStage) {
    

        // Blue Arc
        Arc blueArc = new Arc(200, 200, 150, 150, 0, 90);
        blueArc.setType(ArcType.ROUND);
        blueArc.setStroke(Color.BLUE);
        blueArc.setFill(Color.BLUE);
    
        // Green Arc
        Arc greenArc = new Arc(200, 200, 150, 150, 90, 90);
        greenArc.setType(ArcType.ROUND);
        greenArc.setStroke(Color.GREEN);
        greenArc.setFill(Color.GREEN);
    
        // Yellow Arc
        Arc yellowArc = new Arc(200, 200, 150, 150, 180, 90);
        yellowArc.setType(ArcType.ROUND);
        yellowArc.setStroke(Color.YELLOW);
        yellowArc.setFill(Color.YELLOW);

        // Red Arc
        Arc redArc = new Arc(200, 200, 150, 150, 270, 90);
        redArc.setType(ArcType.ROUND);
        redArc.setStroke(Color.RED);
        redArc.setFill(Color.RED);

        Group circle = new Group(blueArc, greenArc, yellowArc, redArc);

        Button rotate = new Button("Rotate Right");
        rotate.setOnAction(this::processButtonPress);
    
        FlowPane pane = new FlowPane(circle, rotate);
        pane.setAlignment(Pos.CENTER);
        pane.setHgap(20);
        pane.setStyle("-fx-background-color: GRAY");
    
        Scene scene = new Scene(pane, 300, 100);
        primaryStage.setTitle("Four-Color Wheel");
        primaryStage.setScene(scene);
        primaryStage.show();
     
    
    
    } 
    
    
 public void processButtonPress(ActionEvent event)
    {
        Group circle = new Group(blueArc, greenArc, yellowArc, redArc);
        circle.setRotate(90);
    }
}
qjp7pelc

qjp7pelc1#

1-许多局部变量是隐藏字段
2-请使用Java命名约定
3-如果你想旋转某个物体,你需要把它当前的旋转加到Angular 上

public class FourColorWheel extends Application {

private Group circle;
private FlowPane pane;
private Button rotate;
private Arc blueArc, greenArc, yellowArc, redArc;

public void start(Stage primaryStage) {

    // Blue Arc
    blueArc = new Arc(200, 200, 150, 150, 0, 90);
    blueArc.setType(ArcType.ROUND);
    blueArc.setStroke(Color.BLUE);
    blueArc.setFill(Color.BLUE);

    // Green Arc
    greenArc = new Arc(200, 200, 150, 150, 90, 90);
    greenArc.setType(ArcType.ROUND);
    greenArc.setStroke(Color.GREEN);
    greenArc.setFill(Color.GREEN);

    // Yellow Arc
    yellowArc = new Arc(200, 200, 150, 150, 180, 90);
    yellowArc.setType(ArcType.ROUND);
    yellowArc.setStroke(Color.YELLOW);
    yellowArc.setFill(Color.YELLOW);

    // Red Arc
    redArc = new Arc(200, 200, 150, 150, 270, 90);
    redArc.setType(ArcType.ROUND);
    redArc.setStroke(Color.RED);
    redArc.setFill(Color.RED);

    circle = new Group(blueArc, greenArc, yellowArc, redArc);

    rotate = new Button("Rotate Right");
    rotate.setOnAction(this::processButtonPress);

    pane = new FlowPane(circle, rotate);
    pane.setAlignment(Pos.CENTER);
    pane.setHgap(20);
    pane.setStyle("-fx-background-color: GRAY");

    Scene scene = new Scene(pane, 400, 400);
    primaryStage.setTitle("Four-Color Wheel");
    primaryStage.setScene(scene);
    primaryStage.show();

}

public void processButtonPress(ActionEvent event) {

    circle.setRotate(circle.getRotate() + 90);
}
}

结果:

k5ifujac

k5ifujac2#

***前言:**其他答案已经解决了你的问题,但我想我会添加一些解释。

问题

您的代码存在一些问题,下面将讨论这些问题。

未初始化字段

最直接的问题是当您运行程序并按下按钮时出现以下错误。

Exception in thread "JavaFX Application Thread" java.lang.NullPointerException: Children: child node is null: parent = Group@2a18a4be
        at javafx.graphics/javafx.scene.Parent$3.onProposedChange(Parent.java:543)
        at javafx.base/com.sun.javafx.collections.VetoableListDecorator.addAll(VetoableListDecorator.java:233)
        at javafx.base/com.sun.javafx.collections.VetoableListDecorator.addAll(VetoableListDecorator.java:103)
        at javafx.graphics/javafx.scene.Group.<init>(Group.java:106)
        at four_color_wheel.processButtonPress(four_color_wheel.java:76)
        ...

这是在这个方法中抛出的:

public void processButtonPress(ActionEvent event) {
    Group circle = new Group(blueArc, greenArc, yellowArc, redArc);
    circle.setRotate(90);
}

因为blueArcgreenArcyellowArcredArc都为空。JavaFX中的父级不能有null子级。
您的类中有一些从未初始化的字段。相反,您可以在start方法中创建具有相同名称的局部变量。这些局部变量在start方法的上下文中隐藏/隐藏字段。但是processButtonPress方法引用了这些字段(因为start方法的局部变量超出了作用域)。要解决这个问题,只需初始化字段,而不是创建局部变量。
例如,而不是:

// Blue Arc
Arc blueArc = new Arc(200, 200, 150, 150, 0, 90);
blueArc.setType(ArcType.ROUND);
blueArc.setStroke(Color.BLUE);
blueArc.setFill(Color.BLUE);

执行:

// Blue Arc
blueArc = new Arc(200, 200, 150, 150, 0, 90);
blueArc.setType(ArcType.ROUND);
blueArc.setStroke(Color.BLUE);
blueArc.setFill(Color.BLUE);

通过在blueArc = ...前面不使用类型,您可以分配字段,而不是创建局部变量。对所有字段执行相同的操作。

旋转错误组

该方法:

public void processButtonPress(ActionEvent event) {
    Group circle = new Group(blueArc, greenArc, yellowArc, redArc);
    circle.setRotate(90);
}

正在创建新的Group。这导致两个问题:
1.您正在旋转未在UI中显示的Group。因此,旋转没有可见的效果。

  1. JavaFX中的节点不能属于两个父节点。通过创建一个新的Group并向其添加弧,这些弧将首先从其当前Group中隐式删除。这将从显示的UI中删除弧。
    修复方法是引用字段circle,而不是创建新的Group
public void processButtonPress(ActionEvent event) {
    circle.setRotate(90);
}

上面的代码假设您已经初始化了circle字段,如前一节所述。

设置旋转为常量

我假设你想让“圆”在你每次按下按钮时旋转****90度。要做到这一点,你需要 * 添加 * 90度的 * 当前 * 旋转。

circle.setRotation(circle.getRotation() + 90);

否则,使用当前代码,第一次按下按钮时,圆将旋转90度,然后将永远不会再次旋转。

无动画

这不是问题 * 本身 *。然而,对于这类事情,使用动画通常是很好的。它可以让用户清楚地看到他们的操作的结果,也可以帮助引导用户的注意力。您可以使用Timeline来实现动画,但在本例中,使用RotateTransition可能更简洁。更多信息请参见本答案末尾的示例。

不遵循标准命名约定

您应该始终遵循您的团队或组织的命名和格式约定(或者,如果您单独工作,则遵循您选择的约定--保持一致即可)。但是当在像Stack Overflow这样的公共论坛上发布代码时,你应该遵循编程语言的 * 标准 * 命名和格式约定。在Java中,类名应该跟在PascalCase后面,也称为UpperCamelCase
换句话说,你的类应该命名为:

public class FourColorWheel extends Application {
   ...
}

示例

下面是您的代码,其中包含对上述问题的修复。为了使代码更简洁,还进行了一些其他修改,包括:

  • 通用化创建多色“圆”,允许制作具有任意数量颜色的圆。
  • 只保留绝对需要的字段(因为这些对象需要在方法之间引用)。在编程时,尽可能缩小范围通常是一个好主意。
  • 使用HBox而不是FlowPane来给予更好的初始布局。这一变化只是为了举例;使用FlowPane并没有错(假设它是您真实的程序的正确布局)。
  • 在动画运行时禁用该按钮,这样它就不会在旋转过程中意外地重新启动。

代码如下:

import javafx.animation.RotateTransition;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.HBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Arc;
import javafx.scene.shape.ArcType;
import javafx.stage.Stage;
import javafx.util.Duration;

import static javafx.animation.Animation.Status.RUNNING;

public class FourColorWheel extends Application {

    private RotateTransition animation;

    @Override
    public void start(Stage primaryStage) {
        Group circle = createMultiColorCircle(Color.BLUE, Color.GREEN, Color.YELLOW, Color.RED);

        animation = new RotateTransition(Duration.millis(175), circle);
        animation.setByAngle(90);

        Button rotate = new Button("Rotate Right");
        rotate.disableProperty().bind(animation.statusProperty().isEqualTo(RUNNING));
        rotate.setOnAction(this::handleButtonPress);
    
        HBox pane = new HBox(20, circle, rotate);
        pane.setAlignment(Pos.CENTER);
        pane.setPadding(new Insets(20));
    
        Scene scene = new Scene(pane);
        primaryStage.setTitle("Four-Color Wheel");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    private void handleButtonPress(ActionEvent event) {
        event.consume();
        animation.playFromStart();
    }

    private Group createMultiColorCircle(Color... colors) {
        Group circle = new Group();

        double startAngle = 0.0;
        double length = 360.0 / colors.length;
        for (Color color : colors) {
            Arc arc = new Arc(200, 200, 150, 150, startAngle, length);
            arc.setType(ArcType.ROUND);
            arc.setStroke(color);
            arc.setFill(color);
            circle.getChildren().add(arc);

            startAngle += length;
        }

        return circle;
    }
}

它看起来像这样:

eqzww0vc

eqzww0vc3#

如果希望圆的行为更像轮子,请使用以下代码替换按钮处理程序。

public void processButtonPress(ActionEvent event) {
        ((Button) event.getSource()).setDisable(true);
        Timeline timeline = new Timeline(new KeyFrame(Duration.millis(60), actionEvent -> circle.setRotate(circle.getRotate() + 1)));
        timeline.setCycleCount(90);
        timeline.setOnFinished((onFinishEvent) -> {
            ((Button) event.getSource()).setDisable(false);
        });
        timeline.play();
    }

增加@Slaw实现。

public void processButtonPress(ActionEvent event) {
        ((Button) event.getSource()).setDisable(true);
        Timeline timeline = new Timeline(new KeyFrame(Duration.seconds(1), new KeyValue(circle.rotateProperty(), circle.getRotate() + 90)));
        timeline.setOnFinished((onFinishEvent) -> {
            ((Button) event.getSource()).setDisable(false);
        });
        timeline.play();
    }

相关问题