Java作业-4

什么是绑定属性?什么接口定义绑定属性?什么接口定义源对象? int、long、float、double,以及boolean的绑定对象类型是什么?Integer 和 Double 是绑定属性吗? Integer和Double可以在一个绑定中作为源对象吗?
七种面板
如何在一个 FlowPane 和 GridPane中设置节点间的水平间隔和垂直间隔为 8 像素,以及如何在 HBox 和 VBox 中设置间距为 8 像素
四风扇、圆柱、BarCharts、可变网格

什么是绑定属性?什么接口定义绑定属性?什么接口定义源对象? int、long、float、double,以及boolean的绑定对象类型是什么?Integer 和 Double 是绑定属性吗? Integer和Double可以在一个绑定中作为源对象吗?

  • 绑定属性是指能够与其他属性进行绑定的属性。这些属性通常是 Property 类型,例如 SimpleIntegerPropertySimpleStringProperty
  • JavaFX 中定义绑定属性的接口是 javafx.beans.property.Property<T>
  • 源对象通常是指那些可以观察的对象,其值的变化可以被其他对象所观察。这些对象实现了 Observable 接口。
基本数据类型 绑定对象类型
int IntegerProperty
long LongProperty
float FloatProperty
double DoubleProperty
boolean BooleanProperty
  • IntegerDouble 本身是 Java 的封装类型,而不是 JavaFX 的绑定属性。但是,JavaFX 提供了相应的 Property 类型(如 IntegerPropertyDoubleProperty)来使这些基本数据类型具有绑定特性。
  • 不能直接将一个 IntegerProperty 与一个 DoubleProperty 绑定。但是可以使用转换或其他中间步骤来完成。例如创建一个计算绑定,其中一个属性的值是基于另一个属性的值进行计算的。在这种情况下,可以将 DoubleProperty 的值转换为整数,并与 IntegerProperty 进行绑定。

如何将一个节点加入到一个Pane、StackPane、FlowPane、GridPane、BorderPane、HBox、VBox 中?如何从这些面板中移除一个节点?并解释一下这七种面板的特点

面板 添加操作 移除操作 特点
Pane pane.getChildren().add(node); pane.getChildren().remove(node); 基本布局,无特殊布局安排。
StackPane stackPane.getChildren().add(node); stackPane.getChildren().remove(node); 将子节点堆叠在同一位置,默认居中。
FlowPane flowPane.getChildren().add(node); flowPane.getChildren().remove(node); 从左到右或从上到下排列子节点,自动换行。
GridPane gridPane.add(node, columnIndex, rowIndex); gridPane.getChildren().remove(node); 网格布局,按指定行和列放置组件。
BorderPane 根据区域,如:borderPane.setTop(node); borderPane.getChildren().remove(node); 五个区域(上、下、左、右、中心)布局。
HBox hBox.getChildren().add(node); hBox.getChildren().remove(node); 水平盒子,从左到右排列子节点。
VBox vBox.getChildren().add(node); vBox.getChildren().remove(node); 垂直盒子,从上到下排列子节点。

如何在一个 FlowPane 和 GridPane中设置节点间的水平间隔和垂直间隔为 8 像素,以及如何在 HBox 和 VBox 中设置间距为 8 像素?

  • FlowPane:
    – 水平间隔: flowPane.setHgap(8);
    – 垂直间隔: flowPane.setVgap(8);

  • GridPane:
    – 水平间隔: gridPane.setHgap(8);
    – 垂直间隔: gridPane.setVgap(8);

  • HBox:
    – 间距: hBox.setSpacing(8);

  • VBox:
    – 间距: vBox.setSpacing(8);

(创建四个风扇)请写一个程序,将四个风扇按照两行两列置于一个GridPane 中,如图14-45b所示

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Arc;
import javafx.scene.shape.ArcType;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;

public class FourFan extends Application {
    @Override
    public void start(Stage primaryStage) {
        GridPane gridPane = new GridPane();
        // 将四个风扇放入GridPane中
        for (int i = 0; i < 2; i++) {
            for (int j = 0; j < 2; j++) {
                gridPane.add(createRadiationPane(), i, j);
            }
        }

        gridPane.setHgap(10);
        gridPane.setVgap(10);
        Scene scene = new Scene(gridPane, 220, 220);
        primaryStage.setTitle("Fan Layout");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    /** 返回风扇面板,不过长得也不像啊 */
    private Pane createFanPane() {
        Pane fanPane = new Pane();
        double radius = 50; // 设定风扇的半径

        Circle circle = new Circle(radius, radius, radius); // 边界圆形
        circle.setStroke(javafx.scene.paint.Color.BLACK);
        circle.setFill(javafx.scene.paint.Color.WHITE);
        fanPane.getChildren().add(circle);

        for (int i = 0; i < 4; i++) {
            Arc arc = new Arc(radius, radius, radius * 0.9, radius * 0.9, 22.5 + 90 * i, 45);
            arc.setFill(javafx.scene.paint.Color.BLACK); // 设置颜色
            arc.setType(ArcType.ROUND); // 设置Arc的类型
            fanPane.getChildren().add(arc);
        }

        return fanPane;
    }

    /* 这下看懂了 */
    private Pane createRadiationPane() {
        Pane pane = new Pane();
        double centerX = 150, centerY = 150, radius = 100;

        // 绘制中心圆
        Circle circle = new Circle(centerX, centerY, radius);
        circle.setFill(Color.YELLOW);
        pane.getChildren().add(circle);

        // 绘制三个弧形
        for (int i = 0; i < 3; i++) {
            Arc arc = new Arc(centerX, centerY, radius * 0.7, radius * 0.7,  i * 120, 60);
            arc.setFill(Color.BLACK);
            arc.setType(ArcType.ROUND);
            pane.getChildren().add(arc);
        }

        return pane;
    }
}

(显示一个圓柱)请写一个绘制圆柱的程序,如图所示。可以使用如下方法来用虚线显示弧

arc.getStrokeDashArray().addAll(6.0, 21.0);

import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import javafx.scene.shape.Arc;
import javafx.scene.shape.ArcType;
import javafx.scene.shape.Ellipse;
import javafx.scene.shape.Line;
import javafx.stage.Stage;

public class CylinderWithArc extends Application {

    @Override
    public void start(Stage primaryStage) {
        Scene scene = new Scene(getPane(), 300, 300);
        // Scene scene = new Scene(getPane3D(100,150), 300, 300);
        primaryStage.setScene(scene);
        primaryStage.setTitle("显示圆柱");
        primaryStage.show();
    }

    /** 返回圆柱面板 */
    private Pane getPane() {
        Group group = new Group(); // 组

        double X0 = 100;
        double Y0 = 100; // 下圆心坐标
        double height = 100; // 高度
        double radiusX = 50; // X半径
        double radiusY = 20; // Y半径

        // 上边圆
        Ellipse topEllipse = new Ellipse(X0, Y0, radiusX, radiusY);
        topEllipse.setStyle("-fx-stroke: black; -fx-fill: white; "); // 黑色画线,白色填充

        // 下边虚线弧
        Arc dashArc = new Arc(X0, Y0 + height, radiusX, radiusY, 0, 180);
        dashArc.setStyle("-fx-fill: white; -fx-stroke: black;"); // 黑色画线,白色填充
        dashArc.getStrokeDashArray().addAll(6.0, 21.0); // 设置虚线
        dashArc.setType(ArcType.OPEN); // 设置类型

        // 下边实线弧
        Arc solidArc = new Arc(X0, Y0 + height, radiusX, radiusY, 180, 180);
        solidArc.setStyle("-fx-fill: white; -fx-stroke: black;");
        solidArc.setType(ArcType.OPEN);

        // 左边线
        Line left = new Line(X0 - radiusX, Y0, X0 - radiusX, Y0 + height);

        // 右边线
        Line right = new Line(X0 + radiusX, Y0, X0 + radiusX, Y0 + height);

        group.getChildren().addAll(topEllipse, dashArc, solidArc, left, right);
        return new BorderPane(group);
    }

    /* 带简单三维透视转换的图形,但是效果好像不大对*/
    private Pane getPane3D(double observerDistance, double observerAngle) {
        Group group = new Group(); // 创建一个组

        double X0 = 100;
        double Y0 = 100; // 原始圆心坐标
        double height = 100; // 圆柱体的原始高度
        double radiusX = 50; // X轴的原始半径
        double radiusY = 20; // Y轴的原始半径

        // 根据观察者的距离和角度调整椭圆的大小
        double perspectiveFactor = observerDistance / (observerDistance + height);
        double adjustedRadiusX = radiusX * perspectiveFactor;
        double adjustedRadiusY = radiusY * perspectiveFactor;

        // 调整椭圆的位置
        double adjustedY0 = Y0 + height * Math.sin(Math.toRadians(observerAngle));

        Ellipse topEllipse = new Ellipse(X0, Y0, radiusX, radiusY); // 上边的椭圆
        topEllipse.setStyle("-fx-stroke: black; -fx-fill: white;");

        Ellipse bottomEllipse = new Ellipse(X0, adjustedY0, adjustedRadiusX, adjustedRadiusY); // 下边的椭圆
        bottomEllipse.setStyle("-fx-stroke: black; -fx-fill: white;");

        Line left = new Line(X0 - radiusX, Y0, X0 - adjustedRadiusX, adjustedY0); // 左边的线
        Line right = new Line(X0 + radiusX, Y0, X0 + adjustedRadiusX, adjustedY0); // 右边的线

        group.getChildren().addAll(topEllipse, bottomEllipse, left, right);
        return new BorderPane(group);
    }

}

(显示一个柱形图)请写一个程序,使用柱形图来显示一个总成绩的各个组成部分的百分比,包括项目、测试、期中考试和期末考试,如图所示。假设项目占20%并显示为红色,测试占10%并显示为蓝色,期中考试占30%并显示为绿色,期末考试占40% 并显示为橙色。使用Rectangle 类来显示柱形。有兴趣的读者可以探索使用JavaFX 的BarChart 类来进一步学习

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Text;
import javafx.stage.Stage;

public class FourBarCharts extends Application {

    @Override
    public void start(Stage primaryStage) {
        GridPane gridPane = new GridPane();

        // 添加四个柱状图到GridPane中
        gridPane.add(Barchart("项目", 0.2, Color.rgb(22, 33, 67)), 0, 0);
        gridPane.add(Barchart("测试", 0.1, Color.RED), 1, 0);
        gridPane.add(Barchart("期中考试", 0.3, Color.GREEN), 2, 0);
        gridPane.add(Barchart("期末考试", 0.4, Color.BLUE), 3, 0);

        gridPane.setHgap(10);

        Scene scene = new Scene(gridPane, 500, 200);
        primaryStage.setTitle("BarCharts");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    private Pane Barchart(String barName, double percentage, Color color) {
        Pane barPane = new Pane();

        // 根据传入的比例计算柱的高度
        double barHeight = 150 * percentage; // 设置最大高度为150px
        double barY = 150 - barHeight;

        // 创建柱状图
        barName += " - " + percentage * 100 + "%";
        double barWidth = barName.length() * 10;
        Rectangle bar = new Rectangle(barWidth, barHeight); // 宽度为30px,高度根据传入的比例计算
        bar.setFill(color);
        bar.setLayoutY(barY);

        // 创建柱名称
        Text barLabel = new Text(barName);
        barLabel.setLayoutY(barY - 15); // 放在柱的上方

        barPane.getChildren().addAll(bar, barLabel);

        return barPane;
    }
}

(显示一个3 x 3 的网格)请写一个绘制3 x 3 网格的程序,如图所示。使用红色绘制垂直线,蓝色绘制水平线。当窗体改变大小的时候,这些线条自动改变大小

import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Line;

public class GridWithLines extends Application {

    @Override
    public void start(Stage primaryStage) throws Exception {
        int a = 3;
        int b = 3;
        Color verticalLineColor = Color.RED;
        Color horizonLineColor = Color.BLUE;

        Pane pane = drawGrid(a, b, verticalLineColor, horizonLineColor);
        Scene scene = new Scene(pane, 400, 400, false, null);
        primaryStage.setTitle("GridWithLines");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    private Pane drawGrid(int a, int b, Color verticalLineColor, Color horizonLineColor) {
        Pane gridPane = new Pane();

        double cellWidth = 1.0 / a;
        double cellHeight = 1.0 / b;

        // 绘制垂直线
        for (int i = 0; i <= a; i++) {
            Line verticalLine = new Line();
            verticalLine.setStroke(verticalLineColor);
            verticalLine.startXProperty().bind(gridPane.widthProperty().multiply(i * cellWidth));
            verticalLine.endXProperty().bind(verticalLine.startXProperty());
            verticalLine.startYProperty().set(0);
            verticalLine.endYProperty().bind(gridPane.heightProperty());

            gridPane.getChildren().add(verticalLine);
        }

        // 绘制水平线
        for (int i = 0; i <= b; i++) {
            Line horizontalLine = new Line();
            horizontalLine.setStroke(horizonLineColor);
            horizontalLine.startYProperty().bind(gridPane.heightProperty().multiply(i * cellHeight));
            horizontalLine.endYProperty().bind(horizontalLine.startYProperty());
            horizontalLine.startXProperty().set(0);
            horizontalLine.endXProperty().bind(gridPane.widthProperty());

            gridPane.getChildren().add(horizontalLine);
        }

        return gridPane;
    }

}