《Java黑皮书基础篇第10版》 第14章【习题】

Java语言程序设计 习题第十四章

14.2章节习题

14.1 解释 Java GUI 技术的演变

从AWT(Abstract Windows Toolkit),到Swing,再到JavaFX

14.2 解释为何本书采用 JavaFX 教授 Java GUI

新手友好,功能强大,Swing不再更新

14.3章节习题

14.3 如何定义JavaFX主类?start方法的签名是什么?什么是舞台?什么是主舞台?主舞台是自动生成的吗?如何显示一个舞台?可以阻止用户改变舞台大小吗?在程序清单14-1中,可以将第22行的Application.launch(args)替代为launch(args)吗?

通过继承Application类定义JavaFX主类

// start方法签名
public void start(Stage primaryStage)

舞台是场景的载体

主舞台是一个Stage对象

是的,自动创建

使用show()方法显示一个舞台

可以

可以

14.4 请给出下面 JavaFX 程序的输出结果:

import javafx.application.Application;
import javafx.stage.Stage;

public class Test extends Application {      
  public Test() {
    System.out.println("Test constructor is invoked");
  }

  @Override // Override the start method in the Application class
  public void start(Stage primaryStage) {
    System.out.println("start method is invoked");
  }

  public static void main(String[] args) {
    System.out.println("launch application");
    Application.launch(args);
  }
}

输出结果:

launch application
Test constructor is invoked
start method is invoked
14.4章节习题

14.5 如何创建 Scene 对象? 如何在舞台中设置场景? 如何将一个圆置于场景中?

使用构造方法

setScene()方法

将圆置于面板pane中,再由pane作为Scene构造方法的参数

14.6 什么是面板?什么是节点?如何将一个节点置于面板中?可以直接将 Shape 或者 ImageView 置于 Scene 中吗?可以将 Control 或者 Pane 直接置于 Scene 中吗?

面板是pane,将节点中的元素打包,并显示在Scene上

节点是node,可以是一个形状,一个图像视图等

pane.getChildren().add(node)

不可以,需要先放到节点Node中

可以,使用Scene构造方法,因为Parent是Control和Pane的父类

换句话说,类型是Shape和ImageView的节点,不可以直接放到Scene中

类型是Control和Pane的节点,可以直接放到Scene中

14.7 如何创建 Circle? 如何设置它的圆心位置以及半径? 如何设置它的笔划顔色以及填充颜色?

import javafx.scene.shape.Circle;

circle.setCenterX(100);

circle.setCenterY(100);

circle.setRadius(50);

circle.setStroke(Color.BLACK);

circle.setFill(Color.WHITE);

14.5章节习题

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

绑定属性可以将一个目标对象和一个源对象进行绑定

Property接口定义了绑定属性,绑定属性是Property的实例

ObservableValue接口定义了源对象,源对象是ObservableValue的实例

IntegerProperty, LongProperty, DoubleProperty, and BooleanProperty

不是,IntegerProperty和DoubleProperty是绑定属性

不能,IntegerProperty和DoubleProperty可以作为源对象

14.9 遵循JavaFX的绑定属性命名习惯,对于一个IntegerProperty类型且名为age的绑定属性,它的值获取方法、值设置方法以及属性获取方法分别是什么?

getAge()

setAge()

ageProperty()

14.10 可以采用new IntegerProperty(3)来创建IntegerProperty类型的对象吗?如果不可以,正确的创建方法是什么?程序清单14-6中,如果第8行换成d1.bind(d2.multiply(2)),输出将是什么?程序清单14-6中,如果第8行换成d1.bind(d2.add(2),输出将是什么?

不可以,IntegerProperty是抽象类,不可以使用new操作符

new SimpleIntegerProperty(3)

如果更改第八行,就意味着d1总是d2的两倍,如果d2是2,那么d1就是d1 = d2 * 2 = 4

d1 is 4.0 and d2 is 2.0
d1 is 140.4 and d2 is 70.2
d1 is 4.0 and d2 is 2.0
d1 is 72.2 and d2 is 70.2

14.11 什么是单向绑定和双向绑定?是否所有的属性都可以进行双向绑定?请写一个语句,将属性d1和d2进行双向绑定。

目标对象或源对象一方的改变是否会同时引起彼此的改变

不是

14.6章节习题

14.12 如何设置一个节点的样式,使之边框颜色为红色?请修改代码,设置按钮的文本颜色为红色。

node.setStyle("-fx-border: red");
text.setStyle("-fx-fill: red");

14.13 可以旋转面板、文本或者按钮吗? 请修改代码使按钮逆时针旋转15°

可以

btOK.setRotate(-15);
14.7章节习题

14.14

如何创建颜色?

下面创建Color的代码哪里有错:new Color(1.2, 2.3, 3.5, 4)

下面的两个顔色哪个更深,new Color(0,0,0,1)还是 new Color(1,1,1,1)

调用c.darker()改变c中的颜色值吗?

可以通过构造方法,静态方法或预定义标准颜色创建颜色

颜色的范围应该是0-1

颜色 new Color(0, 0, 0, 1) 是完全不透明的黑色,而颜色 new Color(1, 1, 1, 1) 是完全不透明的白色。黑色是最暗的颜色,白色是最亮的颜色,不知道题目怎么定义深/浅

会创建一个新的Color,因为Color不可变

14.15 如何创建具有随机颜色的Color对象?

new Color(Math.random(), Math.random(), Math.random(), 1)

14.16 如何通过setFill方法和使用setStyle方法设置圆对象c的填充顔色为蓝色?

c.setFill(Color.BLUE);
c.setStyle("-fx-fill: blue");
14.8章节习题

14.17 如何创建一个字体名为Courier,大小为20,字体重量为黑体的Font对象?

Font font = Font.font("Courier", Weight.BOLD, 20);

14.18 如何找到系统中所有可用的字体?

getFamilies();
14.9章节习题

14.19 如何从一个URL和一个文件名来创建一个Image对象?

new Image("image/us.gif");
new Image("http://www.xxx.com/us.gif");

14.20 如何从一个Image创建一个ImageView,或者直接从一个文件或URL创建?

Image image = new Image("image/us.gif");
ImageView imageView = new ImageView(image);
ImageView imageView2 = new ImageView("image/us.gif");
ImageView imageView3 = new ImageView("http://www.xxx.com/us.gif");

14.21 可以将一个Image设到多个ImageView上吗? 可以将一个ImageView显示多次吗?

可以,不可以

14.10章节习题

14.22 如何将一个节点加入到一个Pane、StackPane、FlowPane、GrldPane、BorderPane、HBox、VBox 中? 如何从这些面板中移除一个节点?

pane.getChildren().add(node);
pane.getChildren().remove(node);

14.23 如何在一个FlowPane、CridPane、HBox、VBox中设置节点右对齐?

pane.setAlignment(Pos.RIGHT)

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

// FlowPane and GridPane
pane.setHGap(8)
pane.setVGap(8)
  
// HBox and VBox
pane.setSpacing(8);

14.25 如何得到CridPane面板中节点的列和行索引? 如何重新设定CridPane中节点的位置?

// index
pane.getRowIndex(node);
pane.getColumnIndex(node);

// reposition
pane.setRowIndex(node, rowIndex);
pane.setColumnIndex(node, columnIndex);

14.26 FlowPane和HBox或者VBox之间的区别是什么?

FlowPane有多行多列,而H/VBox只有1行/1列

14.11章节习题

14.27 如何显示文本、直线、矩形、圆、椭圆、弧、多边形、折线?

添加一个他们的实例,并add到Scene中

14.28 请写一段代码,显示围绕面板中心中旋转 45° 的一个字符串。

package com.example.demo;

import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.layout.StackPane;
import javafx.scene.text.Text;
import javafx.scene.Scene;
public class Test extends Application {
    @Override
    public void start(Stage primaryStage) {
        StackPane pane = new StackPane();
        Text text = new Text("Hello World!");
        pane.getChildren().add(text);
        pane.setRotate(45);
      
        Scene scene = new Scene(pane, 200, 200);
        primaryStage.setTitle("Test Program");
        primaryStage.setScene(scene);
        primaryStage.show();
    }
}

14.29 请写一段代码,显示一条从(10, 10) 到(70, 30) 的 10 像素宽的粗线。

package com.example.demo;

import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.shape.Line;
public class Test extends Application {
    @Override
    public void start(Stage primaryStage) {
        Pane pane = new Pane();
        Line line = new Line(10, 10, 70, 30);
        line.setStrokeWidth(10);
        pane.getChildren().add(line);

        Scene scene = new Scene(pane, 200, 200);
        primaryStage.setTitle("Test Program");
        primaryStage.setScene(scene);
        primaryStage.show();
    }
}

14.30 请写一段代码,将一个矩形使用红色填充,该矩形的左上角位于(10, 10), 宽度为 100, 高度为 50。

package com.example.demo;

import javafx.application.Application;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.shape.Rectangle;
public class Test extends Application {
    @Override
    public void start(Stage primaryStage) {
        Pane pane = new Pane();
        Rectangle rec = new Rectangle(10, 10, 100, 50);
        pane.getChildren().add(rec);
        rec.setFill(Color.RED);

        Scene scene = new Scene(pane, 200, 200);
        primaryStage.setTitle("Test Program");
        primaryStage.setScene(scene);
        primaryStage.show();
    }
}

14.31 请写一段代码,显示一个圆角的矩形,宽度为 100, 高度为 200, 左上角位于(10, 10), 圆角处的水平直径为 40, 垂直直径为 20。

package com.example.demo;

import javafx.application.Application;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.shape.Rectangle;
public class Test extends Application {
    @Override
    public void start(Stage primaryStage) {
        Pane pane = new Pane();
        Rectangle rec = new Rectangle(10, 10, 100, 200);
        pane.getChildren().add(rec);
        rec.setArcHeight(20);
        rec.setArcWidth(40);

        Scene scene = new Scene(pane, 300, 300);
        primaryStage.setTitle("Test Program");
        primaryStage.setScene(scene);
        primaryStage.show();
    }
}

14.32 请写一段代码,显示一个水平半径为 50, 垂直半径为 100 的椭圆。

package com.example.demo;

import javafx.application.Application;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.shape.Ellipse;
public class Test extends Application {
    @Override
    public void start(Stage primaryStage) {
        Pane pane = new Pane();
        Ellipse ell = new Ellipse(100, 100, 50, 100);
        pane.getChildren().add(ell);

        Scene scene = new Scene(pane, 300, 300);
        primaryStage.setTitle("Test Program");
        primaryStage.setScene(scene);
        primaryStage.show();
    }
}

14.33 请写一段代码,显示一个半径为 50 的圆的上半部轮廓。

package com.example.demo;

import javafx.application.Application;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.shape.Arc;
public class Test extends Application {
    @Override
    public void start(Stage primaryStage) {
        Pane pane = new Pane();
        Arc arc = new Arc(100, 100, 50, 50, 0, 180);
        pane.getChildren().add(arc);

        Scene scene = new Scene(pane, 300, 300);
        primaryStage.setTitle("Test Program");
        primaryStage.setScene(scene);
        primaryStage.show();
    }
}

14.34 请写一段代码,显示一个半径为 50 的圆的下半部,并使用红色填充。

package com.example.demo;

import javafx.application.Application;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.shape.Arc;
public class Test extends Application {
    @Override
    public void start(Stage primaryStage) {
        Pane pane = new Pane();
        Arc arc = new Arc(100, 100, 50, 50, 180, 180);
        arc.setFill(Color.RED);
        pane.getChildren().add(arc);

        Scene scene = new Scene(pane, 300, 300);
        primaryStage.setTitle("Test Program");
        primaryStage.setScene(scene);
        primaryStage.show();
    }
}

14.35 请写一段代码,显示一个连接以下点并用绿色填充的多边形:(20,40),(30,50), (40,90), (90, 10), (10, 30)。

package com.example.demo;

import javafx.application.Application;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.shape.Polygon;
public class Test extends Application {
    @Override
    public void start(Stage primaryStage) {
        Pane pane = new Pane();
        Polygon gon = new Polygon(20, 40, 30, 50, 40, 90, 90, 10, 10, 30);
        gon.setFill(Color.GREEN);
        pane.getChildren().add(gon);

        Scene scene = new Scene(pane, 300, 300);
        primaryStage.setTitle("Test Program");
        primaryStage.setScene(scene);
        primaryStage.show();
    }
}

14.36 请写一段代码,显示一条连接以下点的折线:(20, 40)、(30, 50)、(40, 90)、(90, 10)、(10, 30)。

package com.example.demo;

import javafx.application.Application;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.shape.Polyline;
public class Test extends Application {
    @Override
    public void start(Stage primaryStage) {
        Pane pane = new Pane();
        Polyline line = new Polyline();
        line.getPoints().addAll(20.0, 40.0, 30.0,
                50.0, 40.0, 90.0, 90.0, 10.0, 10.0, 30.0);
        pane.getChildren().add(line);

        Scene scene = new Scene(pane, 300, 300);
        primaryStage.setTitle("Test Program");
        primaryStage.setScene(scene);
        primaryStage.show();
    }
}

编程练习题

14.1 (显示图像)

请写一个程序,在一个网格面板里面显示4个图像,如图14-43a所示

package com.example.demo;

import javafx.application.Application;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.ColumnConstraints;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.RowConstraints;

// 1. Pane的选择:本题需要将4面国旗以2*2的形式排列,涉及到了网格,所以选择GridPane,直接指明放置位置,处理更方便
// 2. 网格处理:图片从互联网下载,每一张长宽不统一,所以先将网格2*2等分,提前指定图片储存的位置大小
// 3. 图片处理:图片从互联网下载,每一张长宽不统一,所以需要将图片等比例缩放,再放入已经处理好的网格中
// 4. 输出结果:把GridPane放入Scene,再把Scene放入Stage
// 需要注意的是,public关键词不可省略,外部JavaFX框架会访问Text类,如果Text没有公开给JavaFX,程序会报异常
public class Test extends Application {
    @Override
    public void start(Stage pStage) {
        // 1. Pane的选择
        GridPane pane = new GridPane();

        // 2. 网格处理
        // 创建两个列约束,每个列宽度为 GridPane 宽度的一半
        ColumnConstraints col1 = new ColumnConstraints();
        col1.setPercentWidth(50);
        ColumnConstraints col2 = new ColumnConstraints();
        col2.setPercentWidth(50);
        pane.getColumnConstraints().addAll(col1, col2);

        // 创建两个行约束,每个行高度为 GridPane 高度的一半
        RowConstraints row1 = new RowConstraints();
        row1.setPercentHeight(50);
        RowConstraints row2 = new RowConstraints();
        row2.setPercentHeight(50);
        pane.getRowConstraints().addAll(row1, row2);

        // 设置水平间距,在我的4张图片中,每张图片Width宽度很大,Height高度很小,所以不需要担心纵列的图片会重叠,但是需要担心横向的图片会重叠
        pane.setHgap(10);

        // 3. 图片处理
        Image image1 = new Image("File:/Users/kevinwang/Desktop/Flag1.png");
        ImageView imageView1 = new ImageView(image1);
        // 保证图片等比例缩放,不会变形
        imageView1.setPreserveRatio(true);
        // 改变图片长宽,把图片的宽度绑定到GridPane宽度的一半,这样下一张图片会不会重叠
        imageView1.fitWidthProperty().bind(pane.widthProperty().multiply(0.5));
        // 改变图片长宽,把图片的高度绑定到GridPane高度的一半,这样下一张图片会不会重叠
        imageView1.fitHeightProperty().bind(pane.heightProperty().multiply(0.5));
        pane.add(imageView1, 0, 0);

        Image image2 = new Image("File:/Users/kevinwang/Desktop/Flag2.png");
        ImageView imageView2 = new ImageView(image2);
        imageView2.setPreserveRatio(true);
        imageView2.fitWidthProperty().bind(pane.widthProperty().multiply(0.5)); // 绑定宽度为一半
        imageView2.fitHeightProperty().bind(pane.heightProperty().multiply(0.5)); // 绑定高度
        pane.add(imageView2, 1, 0);

        Image image3 = new Image("File:/Users/kevinwang/Desktop/Flag3.png");
        ImageView imageView3 = new ImageView(image3);
        imageView3.setPreserveRatio(true);
        imageView3.fitWidthProperty().bind(pane.widthProperty().multiply(0.5)); // 绑定宽度为一半
        imageView3.fitHeightProperty().bind(pane.heightProperty().multiply(0.5)); // 绑定高度
        pane.add(imageView3, 0, 1);

        Image image4 = new Image("File:/Users/kevinwang/Desktop/Flag4.png");
        ImageView imageView4 = new ImageView(image4);
        imageView4.setPreserveRatio(true);
        imageView4.fitWidthProperty().bind(pane.widthProperty().multiply(0.5)); // 绑定宽度为一半
        imageView4.fitHeightProperty().bind(pane.heightProperty().multiply(0.5)); // 绑定高度
        pane.add(imageView4, 1, 1);

        // 4. 输出结果
        pStage.setTitle("Test Program");
        Scene scene = new Scene(pane, 300, 300);
        pStage.setScene(scene);
        pStage.show();
    }
}

输出结果:

在这里插入图片描述

*14.2 (井字棋盘)

请写一个程序,显示一个井字棋盘,如图14-43b所示。一个单元格中可能是X、O或者为空。每个单元格显示什么是随机决定的。X 和 O 是文件x.gif和o.gif中的图像

package com.example.demo;

import javafx.application.Application;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.ColumnConstraints;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.RowConstraints;

// 1. Pane的选择:本题需要将9个图片以3*3的形式排列,涉及到了网格,所以选择GridPane,直接指明放置位置,处理更方便
// (2). 网格处理:和上一道题相比,本题不需要网格处理,因为下载的图片长宽相似
// 2. 图片处理:将图片等比例缩放
// 3. 输出结果:把GridPane放入Scene,再把Scene放入Stage
public class Test extends Application {
    @Override
    public void start(Stage pStage) {
        // 1. Pane的选择
        GridPane pane = new GridPane();

        // 2. 图片处理
        // 导入图片
        Image image1 = new Image("File:/Users/kevinwang/Desktop/true.png");
        Image image2 = new Image("File:/Users/kevinwang/Desktop/false.png");

        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 3; j++) {
                // 需要注意的是,不能将一个ImageView多次放人一个面板或者场景中,因此把ImageView放入循环,每一次刷新即可
                ImageView imageView = new ImageView();
                imageView.setPreserveRatio(true);
                imageView.fitWidthProperty().bind(pane.widthProperty().multiply(0.33));
                imageView.fitHeightProperty().bind(pane.heightProperty().multiply(0.33));

                int temp = (int)(Math.random() * 3);
                if (temp == 0) {
                    imageView.setImage(image1);
                    pane.add(imageView, i, j);
                }
                else if (temp == 1) {
                    imageView.setImage(image2);
                    pane.add(imageView, i, j);
                }
            }
        }

        // 3. 输出结果
        pStage.setTitle("Test Program");
        Scene scene = new Scene(pane, 300, 300);
        pStage.setScene(scene);
        pStage.show();
    }
}

输出结果:

在这里插入图片描述

*14.3 (显示三张牌)

请写一个程序,显示从一副52张的扑克牌中随机选择的三张牌,如图14-43c所 示。牌的图像文件命名为1.png, 2.png, •••, 52.png, 并保存在image/card目录下。 三张牌都是不同的并且是随机选取的

package com.example.demo;

import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.GridPane;
import java.util.ArrayList;

public class Test extends Application {
    @Override
    public void start(Stage pStage) {
        GridPane pane = new GridPane();

        // 为了简单,创建5张牌的Image对象储存在cardList中
        ArrayList<Image> cardList = new ArrayList<>();
        for ( int cardNum = 0; cardNum < 5; cardNum++) {
            Image card = new Image("File:/Users/kevinwang/Desktop/" + cardNum + ".png");
            cardList.add(card);
        }

        // 创建不重复的3个随机数储存在index中
        ArrayList<Integer> index = new ArrayList<>();
        do {
            int temp = (int)(Math.random() * 5);
            if (!index.contains(temp))
                index.add(temp);
        } while (index.size() < 4);

        // 根据index找到对应的图片,并导出图片
        for (int i = 0; i < 3; i++) {
            ImageView view = new ImageView();
            view.setImage(cardList.get(index.get(i)));
            view.setPreserveRatio(true);
            view.fitWidthProperty().bind(pane.widthProperty().multiply(0.33));
            view.fitHeightProperty().bind(pane.heightProperty());
            pane.add(view, i, 0);
            // 居中
            pane.setAlignment(Pos.CENTER);
        }

        // 输出结果
        pStage.setTitle("Test Program");
        Scene scene = new Scene(pane, 300, 300);
        pStage.setScene(scene);
        pStage.show();
    }
}

输出结果:

在这里插入图片描述

14.4 (颜色和字体)

请写一个程序,可以垂直显示 5 个文字,如图14-44a 所示。对每个文字设置一个随机颜色和透明度,并且将每个文字的字体设置为TimesRomes、bold、italic,大小为 22 像素

package com.example.demo;

import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.scene.text.FontPosture;
import javafx.scene.text.FontWeight;
import javafx.scene.text.Text;
import javafx.stage.Stage;
import javafx.scene.Scene;

public class Test extends Application {
    @Override
    public void start(Stage pStage) {
        HBox hPane = new HBox();
        // 思路是将VBox绑定在HBox上
        for (int i = 0; i < 5; i++) {
            VBox pane = new VBox();
            Text j = new Text("J");
            pane.getChildren().add(j);
            Text a = new Text("A");
            pane.getChildren().add(a);
            Text v = new Text("V");
            pane.getChildren().add(v);
            Text a2 = new Text("A");
            pane.getChildren().add(a2);
            Color color1 = new Color(Math.random(), Math.random(), Math.random(), Math.random());
            Font font = Font.font("Impact", FontWeight.BOLD, FontPosture.ITALIC, 22);
            j.setFill(color1);
            j.setFont(font);
            a.setFill(color1);
            a.setFont(font);
            v.setFill(color1);
            v.setFont(font);
            a2.setFill(color1);
            a2.setFont(font);
            hPane.getChildren().add(pane);
            hPane.setSpacing(20);
        }

        Scene scene = new Scene(hPane, 200, 150);
        pStage.setTitle("Test Program");
        pStage.setScene(scene);
        pStage.show();
    }
}

输出结果:

在这里插入图片描述

14.5 (围绕成一个圓的字符)

请写一个程序,显示一个围绕着一个圆显示的字符串“Welcome to Java", 如图14-44b所示

package com.example.demo;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;
import javafx.scene.text.Text;
import javafx.stage.Stage;

public class Test extends Application {
    static String[] message = new String[]{"W", "E", "L", "C", "O", "M", "E", " ", "T", "O", " ", "J", "A", "V", "A"};
    static Font font = Font.font("Times New Roman", FontWeight.BOLD, 28);

    @Override
    public void start(Stage primaryStage) throws Exception {
        Pane pane = new Pane();
        double radius = 75;
        for (int i = 0, currentAngle = 0, rotation = 90; i < message.length; i++, currentAngle += 22, rotation += 22) {
            double x = 105 + radius * Math.cos(Math.toRadians(currentAngle));
            double y = 105 + radius * Math.sin(Math.toRadians(currentAngle));
            Text text = new Text(x, y, message[i]);
            text.setFont(font);
            text.setRotate(rotation);
            pane.getChildren().add(text);
        }

        Scene scene = new Scene(pane, 225, 225);
        primaryStage.setTitle(getClass().getName());
        primaryStage.setScene(scene);
        primaryStage.show();
    }
}

输出结果:

在这里插入图片描述

*14.6(游戏:显示一个象棋棋盘)

请写一个程序显示一个象棋棋盘,其中每个黑白单元格都是一个填充了黑色或者白色的Rectangle,如图14-44c所示

package com.example.demo;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;

public class Test extends Application {
    @Override
    public void start(Stage primaryStage) throws Exception {
        GridPane pane = new GridPane();
        Image white = new Image("File:/Users/kevinwang/Desktop/white.jpeg");
        Image black = new Image("File:/Users/kevinwang/Desktop/black.jpeg");
        for (int row = 0; row < 8; row++) {
            for (int col = 0; col < 8; col++) {
                ImageView viewWhite = new ImageView(white);
                ImageView viewBlack = new ImageView(black);
                viewWhite.fitHeightProperty().bind(pane.heightProperty().multiply(100.0/800));
                viewWhite.fitWidthProperty().bind(pane.widthProperty().multiply(100.0/800));
                viewBlack.fitHeightProperty().bind(pane.heightProperty().multiply(100.0/800));
                viewBlack.fitWidthProperty().bind(pane.widthProperty().multiply(100.0/800));
                if (row % 2 == 0 && col % 2 == 0)
                    pane.add(viewWhite, col, row);
                if (row % 2 == 0 && col % 2 != 0)
                    pane.add(viewBlack, col, row);
                if (row % 2 != 0 && col % 2 == 0)
                    pane.add(viewBlack, col, row);
                if (row % 2 != 0 && col % 2 != 0)
                    pane.add(viewWhite, col, row);
            }
        }
        Scene scene = new Scene(pane, 225, 225);
        primaryStage.setTitle(getClass().getName());
        primaryStage.setScene(scene);
        primaryStage.show();
    }
}

输出结果:

在这里插入图片描述

*14.7 (显示随机的0或者1)

请写一个程序,显示一个10x10的方阵,如图14-45a所示。矩阵中的每个元素是随机产生的 0 或者 1。将每个数字居中显示在一个文本域中。使用 TextField 的 setText 方法来设置0和1作为字符串显示

package com.example.demo;

import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;

public class Test extends Application {
    @Override
    public void start(Stage primaryStage) throws Exception {
        GridPane pane = new GridPane();
        TextField[][] field = new TextField[10][10];
        fillNum(field);
        for (int i = 0; i < 10; i++) {
            for (int j = 0; j < 10; j++) {
                pane.add(field[j][i], j, i);
            }
        }

        Scene scene = new Scene(pane);
        primaryStage.setTitle(getClass().getName());
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    public TextField[][] fillNum(TextField[][] field) {
        for (int i = 0; i < 10; i++) {
            for (int j = 0; j < 10; j++) {
                field[i][j] = new TextField();
                Integer temp = (int)(Math.random() * 2);
                field[i][j].setText(String.valueOf(temp));
                field[i][j].setAlignment(Pos.CENTER);
                field[i][j].setMaxWidth(30);
            }
        }
        return field;
    }
}

输出结果:
在这里插入图片描述

14.8(显示54张牌)

扩充练习题14.3以显示所有54张牌(包括两个王),每行显示9张牌。两个王的

图像文件命名为53.jpg和54.jpg

package com.example.demo;

import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.GridPane;
import java.util.ArrayList;

public class Test extends Application {
    @Override
    public void start(Stage pStage) {
        HBox pane = new HBox();

        // 为了简单,创建5张牌的Image对象储存在cardList中
        ArrayList<Image> cardList = new ArrayList<>();
        for ( int cardNum = 0; cardNum < 5; cardNum++) {
            Image card = new Image("File:/Users/kevinwang/Desktop/" + cardNum + ".png");
            cardList.add(card);
        }

        // 根据index找到对应的图片,并导出图片
        for (int i = 0; i < 5; i++) {
            ImageView view = new ImageView(cardList.get(i));
            view.setPreserveRatio(true);
            view.fitWidthProperty().bind(pane.widthProperty().multiply(0.2));
            view.fitHeightProperty().bind(pane.heightProperty());
            pane.setAlignment(Pos.CENTER);
            pane.getChildren().add(view);
        }

        // 输出结果
        pStage.setTitle("Test Program");
        Scene scene = new Scene(pane, 300, 300);
        pStage.setScene(scene);
        pStage.show();
    }
}

输出结果:

在这里插入图片描述

*14.9(创建四个风扇)

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

package com.example.demo;

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

public class Test extends Application {
    @Override
    public void start(Stage primaryStage){
        Pane pane = new Pane();
        // 本题大概的思路是,通过循环,每创建1个圆,就创建4个弧,通过指定他们各自的坐标,把他们放在合适的位置上
        for (int i = 0; i < 4; i++) {
                int x = 0, y = 0;
                if (i == 0) {
                    x = 100;
                    y = 100;
                }
                if (i == 1) {
                    x = 300;
                    y = 100;
                }
                if (i == 2) {
                    x = 100;
                    y = 300;
                }
                if (i == 3) {
                    x = 300;
                    y = 300;
                }
                Circle circle = new Circle(x, y, 80);
                circle.setStroke(Color.BLACK);
                circle.setFill(Color.TRANSPARENT);
                pane.getChildren().add(circle);

            for (int j = 0; j < 4; j++) {
                int angle = 25;
                if (j == 1) {
                    angle = angle + 90;
                }
                if (j == 2) {
                    angle = angle + 180;
                }
                if (j == 3) {
                    angle = angle + 270;
                }
                Arc arc = new Arc(x, y, 70, 70, angle, 30);
                arc.setType(ArcType.ROUND);
                arc.setFill(Color.BLUE);
                pane.getChildren().add(arc);
            }
        }

        Scene scene = new Scene(pane, 400, 400);
        primaryStage.setTitle(getClass().getName());
        primaryStage.setScene(scene);
        primaryStage.show();
    }
}

输出结果:

在这里插入图片描述

*14.10(显示一个圆柱)

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

package com.example.demo;

import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Arc;
import javafx.scene.shape.ArcType;
import javafx.scene.shape.Ellipse;
import javafx.scene.shape.Line;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.GridPane;
import java.util.ArrayList;

public class Test extends Application {
    @Override
    public void start(Stage pStage) {
        // 一个一个画出来即可
        Pane pane = new Pane();

        Ellipse ellipse = new Ellipse(150, 50, 100, 30);
        ellipse.setStroke(Color.BLACK);
        ellipse.setFill(Color.TRANSPARENT);

        Line line1 = new Line(50, 50, 50, 250);
        Line line2 = new Line(250, 50, 250, 250);

        Arc arc1 = new Arc(150, 250, 100, 30, 0, -180);
        arc1.setType(ArcType.OPEN);
        arc1.setFill(Color.TRANSPARENT);
        arc1.setStroke(Color.BLACK);

        Arc arc2 = new Arc(150, 250, 100, 30, 0, 180);
        arc2.setType(ArcType.OPEN);
        arc2.setFill(Color.TRANSPARENT);
        arc2.setStroke(Color.BLACK);
        // 书中给的提示
        arc2.getStrokeDashArray().addAll(6.0, 21.0);

        pane.getChildren().addAll(ellipse, line1, line2, arc1, arc2);

        pStage.setTitle("Test Program");
        Scene scene = new Scene(pane, 300, 300);
        pStage.setScene(scene);
        pStage.show();
    }
}

输出结果:

在这里插入图片描述

*14.11 (绘制一个笑脸)

请写一个绘制笑脸的程序,如图14-46a所示。

package com.example.demo;

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

public class Test extends Application {
    @Override
    public void start(Stage pStage) {
        // 一个一个画出来即可
        Pane pane = new Pane();

        Circle face = new Circle(100, 100, 80);
        face.setFill(Color.TRANSPARENT);
        face.setStroke(Color.BLACK);

        Circle eye1 = new Circle(70, 70, 10);
        Circle eye2 = new Circle(130, 70, 10);
        Ellipse eye3 = new Ellipse(70, 70, 20, 15);
        Ellipse eye4 = new Ellipse(130, 70, 20, 15);
        eye3.setFill(Color.TRANSPARENT);
        eye3.setStroke(Color.BLACK);
        eye4.setFill(Color.TRANSPARENT);
        eye4.setStroke(Color.BLACK);

        Polygon nose = new Polygon(100, 80, 80, 120, 120, 120);
        nose.setFill(Color.TRANSPARENT);
        nose.setStroke(Color.BLACK);

        Arc mouth = new Arc(100, 120, 50, 20, 0, -180);
        mouth.setType(ArcType.OPEN);
        mouth.setFill(Color.TRANSPARENT);
        mouth.setStroke(Color.BLACK);

        pane.getChildren().addAll(face, eye1, eye2, eye3, eye4, nose, mouth);

        pStage.setTitle("Test Program");
        Scene scene = new Scene(pane, 200, 200);
        pStage.setScene(scene);
        pStage.show();
    }
}

输出结果:

在这里插入图片描述

**14.12 (显示一个柱形图)

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

package com.example.demo;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.chart.BarChart;
import javafx.scene.chart.CategoryAxis;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import javafx.scene.text.Text;

public class Test extends Application {
    @Override
    public void start(Stage primaryStage) {
        CategoryAxis xAxis = new CategoryAxis();
        NumberAxis yAxis = new NumberAxis();
        BarChart<String, Number> barChart = new BarChart<>(xAxis, yAxis);
        barChart.setLegendVisible(false); // 隐藏图例

        XYChart.Series<String, Number> series = new XYChart.Series<>();
        series.getData().add(new XYChart.Data<>("Project", 20));
        series.getData().add(new XYChart.Data<>("Test", 10));
        series.getData().add(new XYChart.Data<>("Midterm", 30));
        series.getData().add(new XYChart.Data<>("Final Exam", 40));

        barChart.getData().add(series);
        barChart.setBarGap(0.3);

        for (XYChart.Data<String, Number> data : series.getData()) {
            Text dataLabel = new Text(data.getYValue().toString());
            StackPane.setAlignment(dataLabel, javafx.geometry.Pos.TOP_CENTER);
            StackPane.setMargin(dataLabel, new javafx.geometry.Insets(-20, 0, 0, 0));
            StackPane bar = (StackPane) data.getNode();
            bar.getChildren().add(dataLabel);
        }

        StackPane root = new StackPane(barChart);
        Scene scene = new Scene(root, 200, 200);
        primaryStage.setTitle(getClass().getName());
        primaryStage.setScene(scene);
        primaryStage.show();
    }
}

输出结果:

在这里插入图片描述

**14.13 (显示一个饼图)

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

package com.example.demo;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.chart.PieChart;
import javafx.stage.Stage;

public class Test extends Application {
    @Override
    public void start(Stage primaryStage) {
        // 创建饼状图数据
        PieChart.Data slice1 = new PieChart.Data("Slice 1", 20);
        PieChart.Data slice2 = new PieChart.Data("Slice 2", 10);
        PieChart.Data slice3 = new PieChart.Data("Slice 3", 30);
        PieChart.Data slice4 = new PieChart.Data("Slice 4", 40);

        // 设置具体数值和标签文本
        slice1.setName("Project 20%");
        slice2.setName("Test 10%");
        slice3.setName("Midterm 30%");
        slice4.setName("Final Exam 40%");

        // 创建饼状图
        PieChart pieChart = new PieChart();
        pieChart.getData().addAll(slice1, slice2, slice3, slice4);

        // 设置饼状图标题
        pieChart.setTitle("Score Distribution");

        // 隐藏图例
        pieChart.setLegendVisible(false);

        // 创建场景并显示
        Scene scene = new Scene(pieChart, 400, 400);
        primaryStage.setTitle(getClass().getName());
        primaryStage.setScene(scene);
        primaryStage.show();
    }
}

输出结果:

在这里插入图片描述

14.14 (显示一个立方体)

请写一个绘制立方体的程序,如图14-47a所示。该立方体应该可以随着窗体的伸缩自动伸缩

package com.example.demo;

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

public class Test extends Application {

    @Override
    public void start(Stage primaryStage) {
        Pane pane = new Pane();
        
        /* Create the bottomLeftAlg 2D-rectangle part of the cube */
        Rectangle bottomLeftAlignedRectangle = new Rectangle(0, 0);
        bottomLeftAlignedRectangle.setFill(Color.TRANSPARENT);
        bottomLeftAlignedRectangle.setStroke(Color.BLACK);

        /* Bind the rectangle to x and y properties of it's container pane,and offset to achieve 3D effect  */
        bottomLeftAlignedRectangle.xProperty().bind(pane.widthProperty().divide(4).subtract(25));
        bottomLeftAlignedRectangle.yProperty().bind(pane.heightProperty().divide(4).add(25));
        bottomLeftAlignedRectangle.widthProperty().bind(pane.widthProperty().divide(2));
        bottomLeftAlignedRectangle.heightProperty().bind(pane.heightProperty().divide(2));

        /* Create the topRightAlignedRectangle */
        Rectangle topRightAlignedRectangle = new Rectangle(0, 0);
        topRightAlignedRectangle.setFill(Color.TRANSPARENT);
        topRightAlignedRectangle.setStroke(Color.BLACK);

        /* Bind to width and height of its container and offset */
        topRightAlignedRectangle.xProperty().bind(pane.widthProperty().divide(4).add(25));
        topRightAlignedRectangle.yProperty().bind(pane.heightProperty().divide(4).subtract(25));
        topRightAlignedRectangle.widthProperty().bind(pane.widthProperty().divide(2));
        topRightAlignedRectangle.heightProperty().bind(pane.heightProperty().divide(2));

        /* Create the lines to connect the font and back rectangles to form the cube/  "rectanguloid"*/
        /* Bind the points in the rectangles to the start and end properties of the connecting lines */
        Line l1 = new Line();
        l1.startXProperty().bind(bottomLeftAlignedRectangle.xProperty());
        l1.startYProperty().bind(bottomLeftAlignedRectangle.yProperty());
        l1.endXProperty().bind(topRightAlignedRectangle.xProperty());
        l1.endYProperty().bind(topRightAlignedRectangle.yProperty());

        Line l2 = new Line();
        l2.startXProperty().bind(bottomLeftAlignedRectangle.xProperty());
        l2.startYProperty().bind(bottomLeftAlignedRectangle.yProperty().add(bottomLeftAlignedRectangle.heightProperty()));
        l2.endXProperty().bind(topRightAlignedRectangle.xProperty());
        l2.endYProperty().bind(topRightAlignedRectangle.yProperty().add(bottomLeftAlignedRectangle.heightProperty()));

        Line l3 = new Line();
        l3.startXProperty().bind(bottomLeftAlignedRectangle.xProperty().add(bottomLeftAlignedRectangle.widthProperty()));
        l3.startYProperty().bind(bottomLeftAlignedRectangle.yProperty().add(bottomLeftAlignedRectangle.heightProperty()));
        l3.endXProperty().bind(topRightAlignedRectangle.xProperty().add(bottomLeftAlignedRectangle.widthProperty()));
        l3.endYProperty().bind(topRightAlignedRectangle.yProperty().add(bottomLeftAlignedRectangle.heightProperty()));

        Line l4 = new Line();
        l4.startXProperty().bind(bottomLeftAlignedRectangle.xProperty().add(bottomLeftAlignedRectangle.widthProperty()));
        l4.startYProperty().bind(bottomLeftAlignedRectangle.yProperty());
        l4.endXProperty().bind(topRightAlignedRectangle.xProperty().add(bottomLeftAlignedRectangle.widthProperty()));
        l4.endYProperty().bind(topRightAlignedRectangle.yProperty());

        pane.getChildren().addAll(bottomLeftAlignedRectangle, topRightAlignedRectangle, l1, l2, l3, l4);
        Scene scene = new Scene(pane, 325, 325);
        scene.xProperty().add(scene.yProperty());
        primaryStage.setTitle(getClass().getName());
        primaryStage.setScene(scene);
        primaryStage.show();
    }
}

输出结果:

在这里插入图片描述

*14.15 (显示一个 STOP 标识)

请写一个绘制 STOP 标识的程序,如图 14-47b 所示。六边形使用红色填充,标识文字使用白色字体

package com.example.demo;

import javafx.application.Application;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Polygon;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.stage.Stage;

public class Test extends Application {

    @Override
    public void start(Stage primaryStage) {
        StackPane pane = new StackPane();
        Polygon polygon = new Polygon();
        pane.getChildren().add(polygon);
        polygon.setFill(Color.RED);
        polygon.setStroke(Color.RED);

        ObservableList<Double> list = polygon.getPoints();
        final double WIDTH = 200, HEIGHT = 200;
        double centerX = WIDTH / 2, centerY = HEIGHT / 2;
        double radius = Math.min(WIDTH, HEIGHT) * 0.4;
        // Add points to the polygon list -> divide Math.PI by 8 for Octagon
        for (int i = 0; i < 8; i++) {
            list.add(centerX + radius * Math.cos(2 * i * Math.PI / 8));
            list.add(centerY - radius * Math.sin(2 * i * Math.PI / 8));
        }
        polygon.setRotate(22.5);

        Text text = new Text("STOP");
        text.setFont(Font.font("Times New Roman", 30));
        text.setFill(Color.WHITE);
        pane.getChildren().add(text);

        Scene scene = new Scene(pane, 200, 200);
        primaryStage.setScene(scene);
        primaryStage.setTitle(getClass().getName());
        primaryStage.show();
    }
}

输出结果:

在这里插入图片描述

*14.16 (显示一个 3 x 3 的网格)

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

package com.example.demo;

import javafx.application.Application;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Line;
import javafx.scene.shape.Polygon;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.stage.Stage;

public class Test extends Application {
    @Override
    public void start(Stage primaryStage) {
        Pane pane = new Pane();

        // 第一条直线是水平方向靠上方的线,默认构造方法(0,0,0,0),起始点X坐标不变,其余根据坐标特点进行绑定
        Line line1 = new Line();
        line1.startYProperty().bind(pane.heightProperty().divide(3));
        line1.endXProperty().bind(pane.widthProperty());
        line1.endYProperty().bind(pane.heightProperty().divide(3));
        line1.setStroke(Color.BLUE);

        // 第二条直线是水平方向靠下方的线,默认构造方法(0,0,0,0),起始点X坐标不变,其余根据坐标特点进行绑定
        Line line2 = new Line();
        line2.startYProperty().bind(pane.heightProperty().multiply(2).divide(3));
        line2.endXProperty().bind(pane.widthProperty());
        line2.endYProperty().bind(pane.heightProperty().multiply(2).divide(3));
        line2.setStroke(Color.BLUE);

        // 第三条直线是垂直方向靠左侧的线,默认构造方法(0,0,0,0),起始点Y坐标不变,其余根据坐标特点进行绑定
        Line line3 = new Line();
        line3.startXProperty().bind(pane.widthProperty().divide(3));
        line3.endXProperty().bind(pane.widthProperty().divide(3));
        line3.endYProperty().bind(pane.heightProperty());
        line3.setStroke(Color.RED);

        // 第四条直线是垂直方向靠右侧的线,默认构造方法(0,0,0,0),起始点Y坐标不变,其余根据坐标特点进行绑定
        Line line4 = new Line();
        line4.startXProperty().bind(pane.widthProperty().multiply(2).divide(3));
        line4.endXProperty().bind(pane.widthProperty().multiply(2).divide(3));
        line4.endYProperty().bind(pane.heightProperty());
        line4.setStroke(Color.RED);

        pane.getChildren().addAll(line1, line2, line3, line4);
        Scene scene = new Scene(pane, 200, 200);
        primaryStage.setScene(scene);
        primaryStage.setTitle(getClass().getName());
        primaryStage.show();
    }
}

输出结果:
在这里插入图片描述

14.17 (游戏:猜字游戏(hangman))

请写一个程序,显示一个图片用于流行的猜字游戏,如图 14-48a所示

package com.example.demo;

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

public class Test extends Application {
    @Override
    public void start(Stage primaryStage) {
        Pane pane = new Pane();

        Arc shelfBase = new Arc(50, 190, 30, 15, 0, 180);
        shelfBase.setFill(Color.TRANSPARENT);
        shelfBase.setStroke(Color.BLACK);

        Polyline shelf = new Polyline(50, 175, 50, 20, 150, 20, 150, 30);

        Circle head = new Circle(150, 50, 20);
        head.setFill(Color.TRANSPARENT);
        head.setStroke(Color.BLACK);

        Line leftArm = new Line(150 - Math.pow(10, 0.5), 67 + Math.pow(10, 0.5), 120, 100);
        Line rightArm = new Line(160 - Math.pow(10, 0.5), 67 + Math.pow(10, 0.5), 180, 100);
        Line body = new Line(150, 70, 150, 120);
        Line leftLeg = new Line(150, 120, 120, 150);
        Line rightLeg = new Line(150, 120, 180, 150);
        pane.getChildren().addAll(shelfBase, shelf, head, leftArm, rightArm, body, leftLeg, rightLeg);

        Scene scene = new Scene(pane, 200, 200);
        primaryStage.setTitle(getClass().getName());
        primaryStage.setScene(scene);
        primaryStage.show();
    }
}

输出结果:

在这里插入图片描述

*14.18 (绘制平方函教)

请写一个程序,绘制表示函数 f ( x ) = x 2 f(x) = x^2 f(x)=x2的图(参见图14-48b)

package com.example.demo;

import javafx.application.Application;
import javafx.collections.ObservableList;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.scene.shape.Line;
import javafx.scene.shape.Polyline;
import javafx.scene.text.Text;
import javafx.stage.Stage;

public class Test extends Application {
    private static final double WIDTH = 400;
    private static final double HEIGHT = 400;

    @Override
    public void start(Stage primaryStage) {
        Polyline polyline = new Polyline();
        ObservableList<Double> list = polyline.getPoints();
        Group group = new Group();

        double scaleFactor = 0.0125;
        for (int x = -100; x <= 100; x++) {
            list.add(x + 200.0);
            list.add(200 - scaleFactor * x * x);
        }
        group.getChildren().add(polyline); // Add points for the Parabola

        Line line1 = new Line(10, 200, 390, 200); // The X-Axis
        group.getChildren().add(line1);

        Line line2 = new Line(200, 30, 200, 390); // The Y-Axis
        group.getChildren().add(line2);

        /* The X-Axis Arrow */
        Line line3 = new Line(390, 200, 370, 190);
        group.getChildren().add(line3);
        Line line4 = new Line(390, 200, 370, 210);
        group.getChildren().add(line4);

        /* The Y-Axis Arrow */
        Line line5 = new Line(200, 30, 190, 50);
        group.getChildren().add(line5);
        Line line6 = new Line(200, 30, 210, 50);
        group.getChildren().add(line6);

        Text text1 = new Text(380, 170, "X");
        Text text2 = new Text(220, 40, "Y");
        group.getChildren().addAll(text1, text2);

        Scene scene = new Scene(new BorderPane(group), WIDTH, HEIGHT);
        primaryStage.setTitle(getClass().getName());
        primaryStage.setScene(scene);
        primaryStage.show();
    }
}

输出结果:
在这里插入图片描述

**14.19 (绘制正弦和余弦函數)

请写一个程序,使用红色绘制正弦函数,使用蓝色绘制余弦函数,如图14-48c所示

package com.example.demo;

import javafx.application.Application;
import javafx.collections.ObservableList;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Line;
import javafx.scene.shape.Polyline;
import javafx.scene.text.Text;
import javafx.stage.Stage;

public class Test extends Application {
    private static final double WIDTH = 400;
    private static final double HEIGHT = 300;

    @Override
    public void start(Stage primaryStage) {
        Polyline polyline = new Polyline();
        ObservableList<Double> sinePoints = polyline.getPoints();
        double scaleFactor = 50;
        //Sine wave points
        for (int x = -200; x <= 200; x++) {
            sinePoints.add(x + 200.0);
            sinePoints.add(200 - scaleFactor * Math.sin((x / 100.0) * 2 * Math.PI));
        }
        polyline.setStroke(Color.RED);
        //Cosine wave points
        Polyline polyline2 = new Polyline();
        ObservableList<Double> cosinePoints = polyline2.getPoints();
        for (int x = -200; x <= 200; x++) {
            cosinePoints.add(x + 200.0);
            cosinePoints.add(200 - scaleFactor * Math.cos((x / 100.0) * 2 * Math.PI));
        }
        polyline2.setStroke(Color.BLUE);
        Group group = new Group();
        group.getChildren().addAll(polyline, polyline2);

        Line line1 = new Line(10, 200, 390, 200); // The X-Axis
        group.getChildren().add(line1);

        Line line2 = new Line(200, 30, 200, 390); // The Y-Axis
        group.getChildren().add(line2);

        /* The X-Axis Arrow */
        Line line3 = new Line(390, 200, 370, 190);
        group.getChildren().add(line3);
        Line line4 = new Line(390, 200, 370, 210);
        group.getChildren().add(line4);

        /* The Y-Axis Arrow */
        Line line5 = new Line(200, 30, 190, 50);
        group.getChildren().add(line5);
        Line line6 = new Line(200, 30, 210, 50);
        group.getChildren().add(line6);

        Text X = new Text(390, 190, "X");
        Text Y = new Text(220, 40, "Y");

        Text zero = new Text(205, 220, "0"); // Center of graph is at point-> 200,200


        Text negPI = new Text(140, 220, "-" + "\u03c0");
        Text negTwoPI = new Text(90, 220, "-2" + "\u03c0");
        Text PI = new Text(250, 220, "\u03c0");
        Text twoPI = new Text(290, 220, "2" + "\u03c0");
        Text threePI = new Text(40, 220, "-3" + "\u03c0");
        Text negThreePI = new Text(340, 220, "3" + "\u03c0");

        group.getChildren().addAll(X, Y, zero, negPI, negTwoPI, PI, twoPI, threePI, negThreePI);

        Scene scene = new Scene(new BorderPane(group), WIDTH, HEIGHT);
        primaryStage.setTitle(getClass().getName());
        primaryStage.setScene(scene);
        primaryStage.show();
    }
}

输出结果:
在这里插入图片描述

**14.20 (绘制一条箭线)

使用静态方法在面板中绘制一条从起点到终点的箭线,使用如下方法头:

public static void drawArrowLine(double startX, double startY, double endX, double endY, Pane pane)

请写一个程序,随机绘制一条箭线,如图 14-49a 所示

package com.example.demo;

import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
import javafx.scene.shape.Line;
import java.util.Random;

public class Test extends Application {
    private static Stage primaryStage;
    private static double WIDTH = 400;
    private static double HEIGHT = 400;

    private static double x1;
    private static double x2;
    private static double y1;
    private static double y2;
    /* Length of main line body */
    private static double L1;
    /* Length of the lines that make the arrow */
    private static double L2;


    public static void drawArrowLine(double startX, double startY, double endX, double endY, Pane pane) {
        double x3, y3, x4, y4;

        Group group = new Group();
        Line line = new Line(startX, startY, endX, endY); // Draw the line for main body of arrow
        L1 = length(line);
        L2 = L1 / 8;
        //Calculate end points for the tip of the arrow
        x3 = endX + (L2 / L1) * (((startX - endX) * Math.cos(Math.toRadians(45.0))) + ((startY - endY) * Math.sin(Math.toRadians(45.0))));
        y3 = endY + (L2 / L1) * (((startY - endY) * Math.cos(Math.toRadians(45.0))) - ((startX - endX) * Math.sin(Math.toRadians(45.0))));
        x4 = endX + (L2 / L1) * (((startX - endX) * Math.cos(Math.toRadians(45.0))) - ((startY - endY) * Math.sin(Math.toRadians(45.0))));
        y4 = endY + (L2 / L1) * (((startY - endY) * Math.cos(Math.toRadians(45.0))) + ((startX - endX) * Math.sin(Math.toRadians(45.0))));

        Line arrowLine1 = new Line(endX, endY, x3, y3);
        Line arrowLine2 = new Line(endX, endY, x4, y4);

        group.getChildren().addAll(line, arrowLine1, arrowLine2);
        pane.getChildren().add(group);

        Scene scene = new Scene(pane, WIDTH, HEIGHT);
        primaryStage.setScene(scene);
        primaryStage.setTitle("Test");
        primaryStage.show();

    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        Test.primaryStage = primaryStage;
        Random random = new Random();
        double bound = WIDTH - 100;
        x1 = random.nextInt((int) bound);
        y1 = random.nextInt((int) bound);
        x2 = random.nextInt((int) bound);
        y2 = random.nextInt((int) bound);
        if (Math.abs(y1 - y2) < 75) {
            y2 += 50;
        }
        if (Math.abs(x1 - x2) < 50) {
            x2 += 50;
        }
        Pane pane = new Pane();
        drawArrowLine(x1, y1, x2, y2, pane);

    }

    public static double findSlope(Line l) {
        return (l.getStartY() - l.getEndY()) / (l.getStartX() - l.getEndX());
    }

    public static double length(Line line) {
        return Math.sqrt((line.getStartX() - line.getEndX())
                * (line.getStartX() - line.getEndX())
                + (line.getStartY() - line.getEndY())
                * (line.getStartY() - line.getEndY()));
    }
}

输出结果:

在这里插入图片描述

*14.21 (两个圓以及它们的距离)

请写一个程序,绘制两个半径为15像素的实心圆,圆心位于一个随机位置;同时绘制一条直线连接两个圆。两个圆心的距离显示在直线上,如图14-49b所示

package com.example.demo;

import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.shape.Circle;
import javafx.scene.text.Text;
import javafx.stage.Stage;
import javafx.scene.shape.Line;
import java.util.Random;

public class Test extends Application {
    private static final double WIDTH = 200;
    private static final double HEIGHT = 200;
    private static final double RADIUS = 15;

    @Override
    public void start(Stage primaryStage) {
        Pane pane = new Pane();

        Circle circle1 = new Circle(Math.random() * WIDTH - RADIUS, Math.random() * HEIGHT - RADIUS, RADIUS);
        Circle circle2 = new Circle(Math.random() * WIDTH - RADIUS, Math.random() * HEIGHT - RADIUS, RADIUS);
        Line line = new Line(circle1.getCenterX(), circle1.getCenterY(), circle2.getCenterX(), circle2.getCenterY());
        double deltaX = circle2.getCenterX() - circle1.getCenterX();
        double deltaY = circle2.getCenterY() - circle1.getCenterY();
        double distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
        Text text = new Text((circle1.getCenterX() + circle2.getCenterX()) / 2, (circle1.getCenterY() + circle2.getCenterY()) / 2, "" + distance);

        pane.getChildren().addAll(circle1, circle2, line, text);

        Scene scene = new Scene(pane, WIDTH, HEIGHT);
        primaryStage.setTitle(getClass().getName());
        primaryStage.setScene(scene);
        primaryStage.show();
    }
}

输出结果:

在这里插入图片描述

*14.22 (连接两个圆)

请写一个程序,绘制两个半径为15像素的圆,圆心位于一个随机位置;同时绘制一条直线连接两个圆。直线不能穿到圆内,如图14-49c所示。

package com.example.demo;

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

public class Test extends Application {
    static final double WIDTH = 200;
    static final double HEIGHT = 200;
    static final double RADIUS = 15;


    @Override
    public void start(Stage primaryStage) {
        Pane pane = new Pane();
        double x1 = Math.random() * (WIDTH - 15);
        double y1 = Math.random() * (HEIGHT - 15);
        double x2 = Math.random() * (WIDTH - 15);
        double y2 = Math.random() * (HEIGHT - 15);

        Circle c1 = new Circle(x1, y1, RADIUS);
        Circle c2 = new Circle(x2, y2, RADIUS);
        c1.setFill(Color.WHITE);
        c1.setStroke(Color.BLACK);
        c2.setFill(Color.WHITE);
        c2.setStroke(Color.BLACK);

        Text text1 = new Text(x1, y1, "1");
        Text text2 = new Text(x2, y2, "2");

        Line line = drawConnectionLine(x1, y1, x2, y2, RADIUS);

        pane.getChildren().addAll(c1, c2, line, text1, text2);

        Scene scene = new Scene(pane, WIDTH, HEIGHT);
        primaryStage.setTitle(getClass().getName());
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    private Line drawConnectionLine(
            double x1, double y1, double x2, double y2, double radius) {
        double d = Math.sqrt((y2 - y1) * (y2 - y1) + (x2 - x1) * (x2 - x1));
        int x11 = (int) (x1 - radius * (x1 - x2) / d);
        int y11 = (int) (y1 - radius * (y1 - y2) / d);
        int x21 = (int) (x2 + radius * (x1 - x2) / d);
        int y21 = (int) (y2 + radius * (y1 - y2) / d);
        return new Line(x11, y11, x21, y21);
    }

    public static void main(String[] args) {
        Application.launch(args);
    }
}

输出结果:
在这里插入图片描述

*14.23 (几何:两个矩形)

请写一个程序,提示用户从命令行输人两个矩形的中心坐标、宽度以及高度。 程序显示两个矩形以及一个文本,表明两个矩形是否有重叠,或者一个是否包含在另外一个内,或者它们是否没有任何重叠, 如图14-50 所示。参考编程练习10.13是如何判断两个矩形之间关系的

package com.example.demo;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Text;
import javafx.stage.Stage;
import java.util.List;
import java.util.Scanner;

public class Test extends Application {
    public static void main(String[] args) {
        // 读取命令行输入,一共8个数字,通过正则表达式依次写入args
        Scanner in = new Scanner(System.in);
        System.out.println("Input 2 rectangles: ");
        args = in.nextLine().split(" ");
        in.close();
        Application.launch(args);
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        Pane pane = new Pane();

        // 获取命令行参数列表,并将其存储在List<String>的变量passedInArgs中
        Parameters params = getParameters();
        List<String> passedInArgs = params.getRaw();

        // 参数错误声明
        if (passedInArgs.size() != 8) {
            System.out.println("Usage: Should be 8 String values.");
        }

        // 把String类型的命令行参数转化为double类型
        double[] index = new double[8];
        for (int i = 0; i < 8; i++) {
            index[i] = Double.parseDouble(passedInArgs.get(i));
        }

        // 创建长方形
        Rectangle rec1 = new Rectangle(index[0], index[1], index[2], index[3]);
        Rectangle rec2 = new Rectangle(index[4], index[5], index[6], index[7]);
        rec1.setStroke(Color.BLACK);
        rec1.setFill(Color.TRANSPARENT);
        rec2.setStroke(Color.BLACK);
        rec2.setFill(Color.TRANSPARENT);
        pane.getChildren().addAll(rec1, rec2);

        // 调用方法判定位置关系
        if (isRectanglesOverlap(rec1, rec2)) {
            Text text = new Text("The 2 rectangles overlap");
            // 将文字绑定在pane底部并居中
            // 首先获取pane的宽度,再将宽度减去文字text本身的长度,剩下的是当前左右两侧空白区域的大小,除以2,得到1侧空白宽度的长度,将这个长度绑定在text文本的x坐标
            text.layoutXProperty().bind(pane.widthProperty().subtract(text.prefWidth(-1)).divide(2));
            // 首先获取pane的高度,再将高度减去文字text本身的高度,剩下的是空白区域,这个空白区域就是text的y坐标,将其绑定到y坐标上
            text.layoutYProperty().bind(pane.heightProperty().subtract(text.prefHeight(-1)));
            pane.getChildren().add(text);
        } else if (isRectangleInside(rec1, rec2) || isRectangleInside(rec2, rec1)) {
            Text text = new Text("One rectangle contains another");
            text.layoutXProperty().bind(pane.widthProperty().subtract(text.prefWidth(-1)).divide(2));
            text.layoutYProperty().bind(pane.heightProperty().subtract(text.prefHeight(-1)));
            pane.getChildren().add(text);
        } else {
            Text text = new Text("The 2 rectangles don't overlap");
            text.layoutXProperty().bind(pane.widthProperty().subtract(text.prefWidth(-1)).divide(2));
            text.layoutYProperty().bind(pane.heightProperty().subtract(text.prefHeight(-1)));
            pane.getChildren().add(text);
        }

        Scene scene = new Scene(pane, 200, 200);
        primaryStage.setTitle(getClass().getName());
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    // 判断是否相交
    private boolean isRectanglesOverlap(Rectangle rect1, Rectangle rect2) {
        return rect1.getBoundsInParent().intersects(rect2.getBoundsInParent());
    }

    // 判断是否内含
    private boolean isRectangleInside(Rectangle rect1, Rectangle rect2) {
        return rect1.getBoundsInParent().contains(rect2.getBoundsInParent());
    }
}

输出结果:

Input 2 rectangles: 
50 60 70 80 40 50 70 80

在这里插入图片描述

*14.24 (几何:在一个多边形内吗?)

请写一个程序,提示用户从命令行输人5个点的坐标。前面4个点构建一个多边形,然后显示该多边形以及一个文本指出第5个点是否在这个多边形中,如图14-51a所示。使用Node的contains方法类测试一个点是否在一个节点中

package com.example.demo;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Polygon;
import javafx.scene.text.Text;
import javafx.stage.Stage;
import java.util.List;
import java.util.Scanner;

public class Test extends Application {
    public static void main(String[] args) {
        // 读取命令行输入,一共10个数字,通过正则表达式依次写入args
        Scanner in = new Scanner(System.in);
        System.out.println("Input 5 points: ");
        args = in.nextLine().split(" ");
        in.close();
        Application.launch(args);
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        Pane pane = new Pane();

        // 获取命令行参数列表,并将其存储在List<String>的变量passedInArgs中
        Parameters params = getParameters();
        List<String> passedInArgs = params.getRaw();

        // 参数错误声明
        if (passedInArgs.size() != 10) {
            System.out.println("Usage: Should be 10 String values.");
        }

        // 把String类型的命令行参数转化为double类型
        double[] index = new double[10];
        for (int i = 0; i < 10; i++) {
            index[i] = Double.parseDouble(passedInArgs.get(i));
        }

        Polygon polygon = new Polygon(index[0], index[1], index[2], index[3], index[4], index[5], index[6], index[7]);
        polygon.setFill(Color.TRANSPARENT);
        polygon.setStroke(Color.BLACK);
        Circle point = new Circle(index[8], index[9], 2);
        pane.getChildren().addAll(polygon, point);

        // 判断位置关系
        if (polygon.contains(index[8], index[9])) {
            Text text = new Text("Point is inside the polygon.");
            text.layoutXProperty().bind(pane.widthProperty().subtract(text.prefWidth(-1)).divide(2));
            text.layoutYProperty().bind(pane.heightProperty().subtract(text.prefHeight(-1)));
            pane.getChildren().add(text);
        } else {
            Text text = new Text("Point is not inside the polygon.");
            text.layoutXProperty().bind(pane.widthProperty().subtract(text.prefWidth(-1)).divide(2));
            text.layoutYProperty().bind(pane.heightProperty().subtract(text.prefHeight(-1)));
            pane.getChildren().add(text);
        }

        Scene scene = new Scene(pane, 200, 200);
        primaryStage.setTitle(getClass().getName());
        primaryStage.setScene(scene);
        primaryStage.show();
    }
}

输出结果:

Input 5 points: 
30 30 100 30 120 150 50 120 60 60

在这里插入图片描述

*14.25 (一个圆上的随机点)

修改编程练习题4.6,在一个圆上创建5个随机点,顺时针连接这5个点构建一个多边形,然后显示这个圆以及多边形,如图14-51b所示

package com.example.demo;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Arc;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Polygon;
import javafx.stage.Stage;
import java.util.ArrayList;

public class Test extends Application {
    private static final double RADIUS = 80;

    @Override
    public void start(Stage primaryStage) throws Exception {
        StackPane pane = new StackPane();

        Circle circle = new Circle(RADIUS);
        circle.setFill(Color.TRANSPARENT);
        circle.setStroke(Color.BLACK);

        ArrayList<Double> list = new ArrayList<>();
        int startAngle = 0;
        int endAngle = 60;

        // 以60度为间隔画弧,记录每次圆弧起点的X & Y坐标,根据这个坐标生成多边形
        for (int i = 0; i < 5; i++) {
            Arc arc = new Arc(100, 100, RADIUS, RADIUS, startAngle, endAngle);
            double startAngleRad = Math.toRadians(startAngle);
            double endAngleRad = Math.toRadians(endAngle);
            double startX = 100 + RADIUS * Math.cos(startAngleRad);
            double startY = 100 + RADIUS * Math.sin(startAngleRad);
            list.add(startX);
            list.add(startY);
            startAngle =  startAngle + 60;
            endAngle = endAngle + 60;
        }

        Polygon polygon = new Polygon(list.get(0), list.get(1), list.get(2), list.get(3), list.get(4), list.get(5), list.get(6), list.get(7), list.get(8), list.get(9));
        polygon.setStroke(Color.BLACK);
        polygon.setFill(Color.TRANSPARENT);
        pane.getChildren().addAll(circle, polygon);

        Scene scene = new Scene(pane, 200, 200);
        primaryStage.setTitle(getClass().getName());
        primaryStage.setScene(scene);
        primaryStage.show();
    }
}

输出结果:

在这里插入图片描述

14.26 (使用 ClockPane 类)

请写一个程序显示两个时钟。第一个时钟的小时、分钟和秒钟的值分别是4、20、45; 第二个时钟的小时、分钟和秒钟的值分别是22、46、15, 如图 14-51c 所示

Test.java

package com.example.demo;

import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.BorderPane;

public class Test extends Application {
    @Override // Override the start method in the Application class
    public void start(Stage primaryStage) {
        // Create a clock and a label
        ClockPane clock = new ClockPane(4, 20 ,55);
        String timeString = clock.getHour() + ":" + clock.getMinute()
                + ":" + clock.getSecond();
        Label lblCurrentTime = new Label(timeString);

        // Place clock and label in border pane
        BorderPane pane = new BorderPane();
        pane.setCenter(clock);
        pane.setBottom(lblCurrentTime);
        BorderPane.setAlignment(lblCurrentTime, Pos.TOP_CENTER);

        ClockPane clock2 = new ClockPane(22, 46 ,15);
        String timeString2 = clock2.getHour() + ":" + clock2.getMinute()
                + ":" + clock2.getSecond();
        Label lblCurrentTime2 = new Label(timeString2);

        // Place clock and label in border pane
        BorderPane pane2 = new BorderPane();
        pane2.setCenter(clock2);
        pane2.setBottom(lblCurrentTime2);
        BorderPane.setAlignment(lblCurrentTime2, Pos.TOP_CENTER);

        // Create a scene and place it in the stage
        Scene scene = new Scene(pane, 250, 250);
        primaryStage.setTitle("DisplayClock"); // Set the stage title
        primaryStage.setScene(scene); // Place the scene in the stage
        primaryStage.show(); // Display the stage

        Stage stage = new Stage(); // Create a new stage
        Scene scene2 = new Scene(pane2, 250, 250);
        stage.setTitle("Second Clock"); // Set the stage title
        stage.setScene(scene2);
        stage.show(); // Display the stage
    }
}

ClockPane.java

package com.example.demo;

import java.util.Calendar;
import java.util.GregorianCalendar;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Line;
import javafx.scene.text.Text;

public class ClockPane extends Pane {
    private int hour;
    private int minute;
    private int second;

    /** Construct a default clock with the current time*/
    public ClockPane() {
        setCurrentTime();
    }

    /** Construct a clock with specified hour, minute, and second */
    public ClockPane(int hour, int minute, int second) {
        this.hour = hour;
        this.minute = minute;
        this.second = second;
    }

    /** Return hour */
    public int getHour() {
        return hour;
    }

    /** Set a new hour */
    public void setHour(int hour) {
        this.hour = hour;
        paintClock();
    }

    /** Return minute */
    public int getMinute() {
        return minute;
    }

    /** Set a new minute */
    public void setMinute(int minute) {
        this.minute = minute;
        paintClock();
    }

    /** Return second */
    public int getSecond() {
        return second;
    }

    /** Set a new second */
    public void setSecond(int second) {
        this.second = second;
        paintClock();
    }

    /* Set the current time for the clock */
    public void setCurrentTime() {
        // Construct a calendar for the current date and time
        Calendar calendar = new GregorianCalendar();

        // Set current hour, minute and second
        this.hour = calendar.get(Calendar.HOUR_OF_DAY);
        this.minute = calendar.get(Calendar.MINUTE);
        this.second = calendar.get(Calendar.SECOND);

        paintClock(); // Repaint the clock
    }

    /** Paint the clock */
    private void paintClock() {
        // Initialize clock parameters
        double clockRadius =
                Math.min(getWidth(), getHeight()) * 0.8 * 0.5;
        double centerX = getWidth() / 2;
        double centerY = getHeight() / 2;

        // Draw circle
        Circle circle = new Circle(centerX, centerY, clockRadius);
        circle.setFill(Color.WHITE);
        circle.setStroke(Color.BLACK);
        Text t1 = new Text(centerX - 5, centerY - clockRadius + 12, "12");
        Text t2 = new Text(centerX - clockRadius + 3, centerY + 5, "9");
        Text t3 = new Text(centerX + clockRadius - 10, centerY + 3, "3");
        Text t4 = new Text(centerX - 3, centerY + clockRadius - 3, "6");

        // Draw second hand
        double sLength = clockRadius * 0.8;
        double secondX = centerX + sLength *
                Math.sin(second * (2 * Math.PI / 60));
        double secondY = centerY - sLength *
                Math.cos(second * (2 * Math.PI / 60));
        Line sLine = new Line(centerX, centerY, secondX, secondY);
        sLine.setStroke(Color.RED);

        // Draw minute hand
        double mLength = clockRadius * 0.65;
        double xMinute = centerX + mLength *
                Math.sin(minute * (2 * Math.PI / 60));
        double minuteY = centerY - mLength *
                Math.cos(minute * (2 * Math.PI / 60));
        Line mLine = new Line(centerX, centerY, xMinute, minuteY);
        mLine.setStroke(Color.BLUE);

        // Draw hour hand
        double hLength = clockRadius * 0.5;
        double hourX = centerX + hLength *
                Math.sin((hour % 12 + minute / 60.0) * (2 * Math.PI / 12));
        double hourY = centerY - hLength *
                Math.cos((hour % 12 + minute / 60.0) * (2 * Math.PI / 12));
        Line hLine = new Line(centerX, centerY, hourX, hourY);
        hLine.setStroke(Color.GREEN);

        getChildren().clear();
        getChildren().addAll(circle, t1, t2, t3, t4, sLine, mLine, hLine);
    }

    @Override
    public void setWidth(double width) {
        super.setWidth(width);
        paintClock();
    }

    @Override
    public void setHeight(double height) {
        super.setHeight(height);
        paintClock();
    }
}

输出结果:
在这里插入图片描述

*14.27 (绘制一个详细的时钟)

修改14.12节的 ClockPane 类,绘制一个包含小时和分钟更加详细信息的时钟,如图 14-52a 所示。

可借鉴

https://blog.csdn.net/weixin_43914658/article/details/109638858

https://blog.csdn.net/qq_52181283/article/details/121173560

*14.28(随机时间)

修改 ClockPane 类, 添加三个类型的属性hourHandVisible、minuteHandVisible、secondHandVisible以及相关的访问器和转变器方法。可以使用set方法来使一个指针可见或者不可见。请写一个测试程序,只显示时针和分针。小时和分钟的值随机产生。小时的值在0-11之间,分钟的值是0或者30,如图14-52b所示

package com.example.demo;

import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Line;
import javafx.scene.shape.Circle;
import javafx.scene.text.Text;
import javafx.stage.Stage;
import java.util.Calendar;
import java.util.GregorianCalendar;

public class Test extends Application {

    private static final int HOUR_UPPER_BOUND = 12;
    private static final int MIN_UPPER_BOUND = 30;

    @Override
    public void start(Stage primaryStage) {
        CustomClockPane clock = new CustomClockPane((int) (Math.random() * HOUR_UPPER_BOUND),
                (int) (Math.random() * MIN_UPPER_BOUND), 0);
        clock.setSecondHandVisible(false);
        String time = clock.getHour() + ":" + clock.getMinute() + ":" + clock.getSecond();
        Label currentTimeLabel = new Label(time);

        BorderPane pane = new BorderPane();
        pane.setCenter(clock);
        pane.setBottom(currentTimeLabel);
        BorderPane.setAlignment(currentTimeLabel, Pos.TOP_CENTER);
        Scene scene = new Scene(pane, 250, 250);
        primaryStage.setTitle(getClass().getName());
        primaryStage.setScene(scene);
        primaryStage.show();
    }
}

class CustomClockPane extends Pane {
    private int hour;
    private int minute;
    private int second;
    private boolean hourHandVisible = true;
    private boolean minuteHandVisible = true;
    private boolean secondHandVisible = true;

    public CustomClockPane() {
        setTime();
    }

    public CustomClockPane(int hour, int minute, int second) {
        this.hour = hour;
        this.minute = minute;
        this.second = second;
        render();

    }

    public boolean isHourHandVisible() {
        return hourHandVisible;
    }

    public CustomClockPane setHourHandVisible(boolean hourHandVisible) {
        this.hourHandVisible = hourHandVisible;
        return this;
    }

    public boolean isMinuteHandVisible() {
        return minuteHandVisible;
    }

    public CustomClockPane setMinuteHandVisible(boolean minuteHandVisible) {
        this.minuteHandVisible = minuteHandVisible;
        return this;
    }

    public boolean isSecondHandVisible() {
        return secondHandVisible;
    }

    public CustomClockPane setSecondHandVisible(boolean secondHandVisible) {
        this.secondHandVisible = secondHandVisible;
        return this;
    }


    void setHour(int hour) {
        this.hour = hour;
        render();
    }


    void setMinute(int minute) {
        this.minute = minute;
        render();
    }


    void setSecond(int second) {
        this.second = second;
        render();
    }

    int getHour() {
        return this.hour;
    }

    int getMinute() {
        return this.minute;
    }

    int getSecond() {
        return this.second;
    }

    void setTime() {
        Calendar calendar = new GregorianCalendar();

        this.hour = calendar.get(Calendar.HOUR_OF_DAY);
        this.minute = calendar.get(Calendar.MINUTE);
        this.second = calendar.get(Calendar.SECOND);

        render();
    }

    private void render() {
        double clockRadius = Math.min(getWidth(), getHeight()) * 0.8 * 0.5;
        double centerX = getWidth() / 2;
        double centerY = getHeight() / 2;

        Circle circle = new Circle(centerX, centerY, clockRadius);
        circle.setFill(Color.WHITE);
        circle.setStroke(Color.BLACK);
        Text t1 = new Text(centerX - 5, centerY - clockRadius + 12, "12");
        Text t2 = new Text(centerX - clockRadius + 3, centerY + 5, "9");
        Text t3 = new Text(centerX + clockRadius - 10, centerY + 3, "3");
        Text t4 = new Text(centerX - 3, centerY + clockRadius - 3, "6");

        double sLength = clockRadius * 0.8;
        double secondX = centerX + sLength *
                Math.sin(second * (2 * Math.PI / 60));
        double secondY = centerY - sLength *
                Math.cos(second * (2 * Math.PI / 60));
        Line sLine = new Line(centerX, centerY, secondX, secondY);
        sLine.setStroke(Color.RED);

        double mLength = clockRadius * 0.65;
        double xMinute = centerX + mLength *
                Math.sin(minute * (2 * Math.PI / 60));
        double minuteY = centerY - mLength *
                Math.cos(minute * (2 * Math.PI / 60));
        Line mLine = new Line(centerX, centerY, xMinute, minuteY);
        mLine.setStroke(Color.BLUE);

        double hLength = clockRadius * 0.5;
        double hourX = centerX + hLength *
                Math.sin((hour % 12 + minute / 60.0) * (2 * Math.PI / 12));
        double hourY = centerY - hLength *
                Math.cos((hour % 12 + minute / 60.0) * (2 * Math.PI / 12));
        Line hLine = new Line(centerX, centerY, hourX, hourY);
        hLine.setStroke(Color.GREEN);

        getChildren().clear();
        getChildren().addAll(circle, t1, t2, t3, t4);

        if (secondHandVisible) {
            getChildren().add(sLine);
        }

        if (minuteHandVisible) {
            getChildren().add(mLine);
        }

        if (hourHandVisible) {
            getChildren().add(hLine);
        }
    }

    @Override
    public void setWidth(double width) {
        super.setWidth(width);
        render();
    }

    @Override
    public void setHeight(double height) {
        super.setHeight(height);
        render();
    }
}

输出结果:

在这里插入图片描述

**14.29 (游戏:豆机)

请写一个程序,显示编程练习题 7.21 中介绍的豆机,如图 14-52c 所示

package com.example.demo;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.shape.Line;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Polyline;
import javafx.stage.Stage;

public class Test extends Application {
    @Override
    public void start(Stage primaryStage) {
        Pane pane = new Pane();

        Polyline polyline = new Polyline(120, 50, 120, 100, 30, 240, 30 ,280, 270, 280, 270, 240, 180, 100, 180, 50);

        Line line1 = new Line(60, 280, 60, 240);
        Line line2 = new Line(90, 280, 90, 240);
        Line line3 = new Line(120, 280, 120, 240);
        Line line4 = new Line(150, 280, 150, 240);
        Line line5 = new Line(180, 280, 180, 240);
        Line line6 = new Line(210, 280, 210, 240);
        Line line7 = new Line(240, 280, 240, 240);

        Circle circle1 = new Circle(60, 240, 5);
        Circle circle2 = new Circle(90, 240, 5);
        Circle circle3 = new Circle(120, 240, 5);
        Circle circle4 = new Circle(150, 240, 5);
        Circle circle5 = new Circle(180, 240, 5);
        Circle circle6 = new Circle(210, 240, 5);
        Circle circle7 = new Circle(240, 240, 5);

        Circle circle8 = new Circle(60, 240, 5);
        Circle circle9 = new Circle(75, 220, 5);
        Circle circle10 = new Circle(90, 200, 5);
        Circle circle11 = new Circle(105, 180, 5);
        Circle circle12 = new Circle(120, 160, 5);
        Circle circle13 = new Circle(135, 140, 5);
        Circle circle14 = new Circle(150, 120, 5);

        Circle circle15 = new Circle(105, 220, 5);
        Circle circle16 = new Circle(135, 220, 5);
        Circle circle17 = new Circle(165, 220, 5);
        Circle circle18 = new Circle(195, 220, 5);
        Circle circle19 = new Circle(225, 220, 5);

        Circle circle20 = new Circle(120, 200, 5);
        Circle circle21 = new Circle(150, 200, 5);
        Circle circle22 = new Circle(180, 200, 5);
        Circle circle23 = new Circle(210, 200, 5);

        Circle circle24 = new Circle(135, 180, 5);
        Circle circle25 = new Circle(165, 180, 5);
        Circle circle26 = new Circle(195, 180, 5);

        Circle circle27 = new Circle(150, 160, 5);
        Circle circle28 = new Circle(180, 160, 5);

        Circle circle29 = new Circle(165, 140, 5);
        
        pane.getChildren().addAll(polyline, line1, line2, line3, line4, line5, line6, line7,
                                    circle1, circle2, circle3, circle4, circle5, circle6, circle7,
                                    circle8, circle9, circle10, circle11, circle12, circle13, circle14,
                                    circle15, circle16, circle17, circle18, circle19,
                                    circle20, circle21, circle22, circle23, circle24, circle25, circle26,
                                    circle27, circle28, circle29);

        Scene scene = new Scene(pane, 300, 300);
        primaryStage.setTitle(getClass().getName());
        primaryStage.setScene(scene);
        primaryStage.show();
    }
}

输出结果:

在这里插入图片描述

  • 8
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是一个简单的JavaFX代码示例,用于绘制国国旗(五星红旗): ``` import javafx.application.Application; import javafx.scene.Group; import javafx.scene.Scene; import javafx.scene.paint.Color; import javafx.scene.shape.Polygon; import javafx.scene.shape.Rectangle; import javafx.stage.Stage; public class ChinaFlag extends Application { @Override public void start(Stage primaryStage) { Group root = new Group(); // 画国旗背景 Rectangle bg = new Rectangle(0, 0, 600, 400); bg.setFill(Color.RED); root.getChildren().add(bg); // 画大星星 Polygon bigStar = new Polygon( 300, 100, 330, 160, 390, 160, 340, 195, 360, 250, 300, 220, 240, 250, 260, 195, 210, 160, 270, 160 ); bigStar.setFill(Color.YELLOW); root.getChildren().add(bigStar); // 画四个小星星 Polygon smallStar1 = new Polygon( 320, 120, 330, 130, 340, 120, 330, 110 ); smallStar1.setFill(Color.YELLOW); root.getChildren().add(smallStar1); Polygon smallStar2 = new Polygon( 360, 120, 370, 130, 380, 120, 370, 110 ); smallStar2.setFill(Color.YELLOW); root.getChildren().add(smallStar2); Polygon smallStar3 = new Polygon( 320, 170, 330, 180, 340, 170, 330, 160 ); smallStar3.setFill(Color.YELLOW); root.getChildren().add(smallStar3); Polygon smallStar4 = new Polygon( 360, 170, 370, 180, 380, 170, 370, 160 ); smallStar4.setFill(Color.YELLOW); root.getChildren().add(smallStar4); Scene scene = new Scene(root, 600, 400); primaryStage.setTitle("China Flag"); primaryStage.setScene(scene); primaryStage.show(); } public static void main(String[] args) { launch(args); } } ``` 这个代码将绘制一个具有红色背景和一个大黄色五角星,以及四个小黄色五角星的国国旗。你可以运行这个程序并查看结果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值