【问题标题】:hide a group of shapes with checkbox (JavaFX)用复选框隐藏一组形状(JavaFX)
【发布时间】:2021-09-15 07:38:08
【问题描述】:

我正在编写一些具有 UI 并绘制彩虹的代码。有一个复选框,单击时会出现彩虹。如果不勾选,彩虹就会消失。有一个私有类负责复选框所做的操作。里面有一个 if-else 语句,说明如果选中该框,则彩虹的 setVisible 为真,否则为假。我的代码遇到的问题是该框无法正常工作。任何地方似乎都没有任何语法错误,所以我不确定错误在哪里。除了setVisible,我没学过其他方法。

下面是我的代码:

import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.control.*;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.*;
import javafx.scene.shape.Arc;
import javafx.scene.shape.ArcType;
import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;
import javafx.scene.text.Text;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.paint.Color;
import javafx.scene.shape.Ellipse;
import javafx.scene.shape.Rectangle;


public class Main extends Application {
    private Pane root;

    private CheckBox rainbowBox;


    private Rainbow r1;


    @Override
    public void start(Stage primaryStage) {

        root = new Pane();

        r1 = new Rainbow(450, 425);

        rainbowBox = new CheckBox("rainbow");
        rainbowBox.setLayoutX(10);
        rainbowBox.setLayoutY(10);


        root.getChildren().addAll(rainbowBox);


        rainbowEvent showRainbow = new rainbowEvent();
        rainbowBox.setOnAction(showRainbow);


        Scene scene = new Scene(root, 650, 500);
        primaryStage.setTitle("example");
        primaryStage.setScene(scene);
        primaryStage.show();

    }

    public static void main(String[] args) {

        Application.launch(args);
    }


    private class Rainbow {

        private Group rainbowGroup;

        public Rainbow(int x, int y) {
            Ellipse circle1 = new Ellipse(x, y, 300, 300);
            circle1.setFill(Color.RED);

            Ellipse circle2 = new Ellipse(x, y, 290, 290);
            circle2.setFill(Color.ORANGE);

            Ellipse circle3 = new Ellipse(x, y, 280, 280);
            circle3.setFill(Color.YELLOW);

            Ellipse circle4 = new Ellipse(x, y, 270, 270);
            circle4.setFill(Color.GREEN);

            Ellipse circle5 = new Ellipse(x, y, 260, 260);
            circle5.setFill(Color.BLUE);

            Ellipse circle6 = new Ellipse(x, y, 250, 250);
            circle6.setFill(Color.PURPLE);

            Ellipse circle7 = new Ellipse(x, y, 240, 240);
            circle7.setFill(Color.WHITE);

            root.getChildren().addAll(circle1, circle2, circle3, circle4, circle5, circle6, circle7);
        }

        public Group getNodes() {
            return rainbowGroup;
        }

    }


    private class rainbowEvent implements EventHandler<ActionEvent> {

        @Override
        public void handle(ActionEvent event) {
            if (event.getSource() == r1.rainbowGroup) {
                r1.rainbowGroup.setVisible(true);
            } else {
                r1.rainbowGroup.setVisible(false);
            }

        }
    }
}

【问题讨论】:

  • 注意:你还没有初始化rainbowGroup,所以它永远是null。
  • 请使用java命名约定

标签: java events javafx methods event-handling


【解决方案1】:

首先,正如 VGR 所指出的,确保初始化 rainbowGroup 并将省略号放在该组中,然后将该组放在根父级中。如果你不初始化rainbowGroup,那么你会得到一个 NPE。而且,如果您实际上没有将省略号放入组中,那么您将无法通过所述组一次性控制它们的可见性。

第二,你的事件处理器实现:

private class rainbowEvent implements EventHandler<ActionEvent> {

    @Override
    public void handle(ActionEvent event) {
        if (event.getSource() == r1.rainbowGroup) {
            r1.rainbowGroup.setVisible(true);
        } else {
            r1.rainbowGroup.setVisible(false);
        }
    } 
} 

注意:遵循标准 Java 命名约定,类以大写字母开头(即应该是RainbowEvent)。尽管您可能还想更改名称,因为当前名称并不能真正描述它的作用(类不是事件)。

根据event.getSource() == r1.rainbowGroup 确定要做什么。由于您在CheckBox 上设置了处理程序,该条件将永远为真,因此只会执行else 块。它也从不查询复选框的选中状态。将实现更改为:

// using lambda expression instead of nested class
rainbowBox.setOnAction(e -> r1.getNodes().setVisible(rainbowBox.isSelected()));

应该适合你。另一种选择是使用绑定:

r1.getNodes().visibleProperty().bind(rainbowBox.selectedProperty());

绑定,或者以其他方式观察selected 属性,可能是更合适的选择。如果复选框的选中状态可以通过编程方式更改,则尤其如此。


请注意,您实际上并不经常需要查询事件的来源。并且事件的源始终是当前处理注册处理程序的事件的节点。因此,在您的代码中,由于您只将处理程序添加到 CheckBox,因此源将始终CheckBox

【讨论】:

  • 传播违反命名约定 ;)
  • @kleopatra 好吧,从技术上讲,我只是在引用代码:p 但我添加了一条注释来解决错误的类名。
  • 是的,传播 == 引用 感谢您的编辑:)
猜你喜欢
  • 2016-05-03
  • 2013-08-10
  • 1970-01-01
  • 2013-11-09
  • 2016-02-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多