封面 illusion by 梅原せい

59.GUI with JavaFX

Previously, Java GUI classes are Abstract Windows Toolkit (AWT) and Swing
○ Depreciated, no longer updated
● JavaFX is the new framework that replaces them since Java 8
注意这里提供的JavaFX版本是61版本,对应的是JDK17。
JavaFX根本就没有流行过,现在JavaFX已经被Java SE 9及更高版本所取代,其组件已经加入公共库。所以并不需要过于深入的学习。

1.JavaFX Advantages

Stage: top level container to be displayed 显示的顶层容器
Scene: Scene objects are placed in a Stage object
场景对象被放置在一个舞台对象中
Node: Node objects are placed in a Scene object
节点对象被放置在一个场景对象中
■ Node objects are visual components such as buttons, images, panes, and shapes 节点对象是视觉组件
■ Node can contain other nodes
节点可以包含其他节点
pFJDaZT.png

2.Say hello to the GUI world

import javafx.application.Application; 
import javafx.stage.Stage; 
import javafx.scene.Scene; 
import javafx.scene.control.Button; 
public class JavaFXTesting extends Application { 
@Override 
public void start(Stage primaryStage) { 
Button helloButton = new Button("Hello World!"); 
Scene scene = new Scene(helloButton, 200, 250); 
primaryStage.setTitle("My First JavaFX Program"); 
primaryStage.setScene(scene); 
primaryStage.show(); 
} 
public static void main(String[] args) { 
launch(args); 
} 
}
1.方法一定包含于extends Application
2.方法用于放置node对象
比如此处将Button放入Scene中
3.当然stage对象中显示scene对象
4.Scene对象按Scene(node,width,height)创建
构造函数指定宽度、高度和在场景中放置节点
5.一个stage对象是一个窗口
当应用程序启动时,JVM会自动创建一个称为primary object的阶段对象。
将nodes放置在Pane 中,以设置场景中的the location和the size。
pFJDddU.png

3.Button in a Pane

package fxtest;

import javafx.application.Application;
import javafx.scene.Scene; 
import javafx.scene.control.Button; 
import javafx.stage.Stage;
import javafx.scene.layout.StackPane;
public class FXtest extends Application { 
    @Override 
    public void start(Stage primaryStage) {
    // Create a scene and place a button in the scene
    StackPane pane = new StackPane();
pane.getChildren().add(new Button("OK"));
//这两步简化为StackPane pane = new StackPane(new Button("OK"));
    Scene scene= new Scene(pane, 200, 50); 
    primaryStage.setTitle("Button in a pane");
    // Set the stage titlel
    primaryStage.setScene(scene); 
    // Place the scene in the stage 
    primaryStage.show(); // Display the stage
    }  
    public static void main(String[] args){
        launch(args);
        }
}
pFJDBi4.png

4.Circle

Circle is displayed in the center of scene, but not after window is resized.初始界面处于中心,调整后不处于。
package circlefx;

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

public class CircleFX extends Application {
     public void start(Stage primaryStage) {
//Create a circle and set its properties
         Circle circle = new Circle();
         circle.setCenterX(150);
         circle.setCenterY(150);
         circle.setRadius(50);
         circle.setStroke(Color.BLACK);
         circle.setFill(Color.WHITE);
//显而易见的位置XYJava Coordinate System(以左上为原点)黑边白填充
//Create a pane to hold the circle
        Pane pane  =new Pane();
        pane.getChildren().add(circle);
//create a scene and place it in the stage
        Scene scene =new Scene(pane,300,300);
        primaryStage.setTitle("Showcircle");
        primaryStage.setScene(scene);
        primaryStage.show();
          }
    public static void main(String[] args) {
        launch(args);
    }    
}
当然,就会想到如果能把Circle绑定在窗口中心就好了。
import javafx.application.Application;
import javafx.scene.Scene; 
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;

public class CircleFX extends Application {
     public void start(Stage primaryStage) {
          //Create a pane to hold the circle
        Pane pane  =new Pane();
         //Create a circle and set its properties
         Circle circle = new Circle();
     circle.centerXProperty().bind(pane.widthProperty().divide(2));
     circle.centerYProperty().bind(pane.widthProperty().divide(2));[1]
         circle.setRadius(50);
         circle.setStroke(Color.BLACK);
         circle.setFill(Color.WHITE);
         pane.getChildren().add(circle);[2]
    //create a scene and place it in the stage
        Scene scene =new Scene(pane,300,300);
        primaryStage.setTitle("Showcircle");
        primaryStage.setScene(scene);
        primaryStage.show();
          }
    public static void main(String[] args) {
        launch(args);
    }    
}
对pane操作的理解: [1]这些线使用属性绑定来确保圆的中心始终是窗格宽度的一半。这意味着,如果窗格的宽度改变,圆的中心将自动相应地调整。 [2]将“圆”节点添加到窗格的子节点,使其成为窗格图形内容的一部分。
pFJDWdO.png

5.Color

setFill和setstroke用color代码 当然也包含了RGB的输入 Use RGBA (red, green, blue, alpha/opacity) model 自定义创建 ○ values are from 0.0 (darkest) to 1.0 (lightest) ○ example: C
Color color = new Color(0.78, 0.14, 0.333, 0.51);
circle.setStroke(color);
circle.setFill(color);
特别的,Color.TRANSPARENT=透明。

6.Font, Label and StackPane

Label label = new Label("JavaFX");
label.setFont(Font.font("Times New Roman",FontWeight.BOLD, FontPosture.ITALIC, 20));
//字体种类、粗细、字体姿势、大小
pane.getChildren().add(label);
Label = new Label("JavaFX");

7.Image and ImageView

//Create a pane to hold the image views
Pane pane = new HBox(10);//盒子,其中子元素间隔为10
pane.setPadding(new Insets(5, 5, 5, 5));
//pane 的内边距(padding),分别是上下左右
Image image = new Image("image/us.gif");
//导入图片
pane.getChildren().add(new ImageView(image));
setFitweight
setFitHeight
//变换宽长
setRotate(90)
//旋转(顺时针90度)

8.Layout Panes

JavaFX provides many types of panes for organizing nodes
Class JavaFX为组织节点提供了多种类型的窗格。
Description
Pane
Base class for layout panes. It contains the getChildren() method for returning a list of nodes in the pane.
Pane 是所有布局窗格的基类。它本身没有特定的布局策略,但提供了一个容器,可以通过 getChildren()
方法获取其子节点列表。你可以使用它作为其他布局的基础。
StackPane
Places the nodes on top of each other in the center of the pane.
StackPane 将其子节点堆叠在一起,居中显示。后添加的节点将覆盖先添加的节点,因此最后添加的节点将显示在最上面。
FlowPane
Places the nodes row-by-row horizontally or column-by-column vertically. FlowPane 将其子节点按行或列的方式排列。它会自动换行,根据需要创建新行或列,以适应容器的大小。
GridPane
Places the nodes in the cells in a two-dimensional grid.
GridPane 将子节点放置在二维网格中,可以通过指定行和列来控制子节点的位置。这是一个强大的布局,适用于复杂的 UI 布局。
BorderPane
Places the nodes in the top, right, bottom, left, and center regions.
BorderPane 将其子节点放置在顶部、右侧、底部、左侧和中心的不同区域。通常用于创建简单的页面布局,例如典型的主页面结构。
HBox
Places the nodes in a single row.
将节点放在一行中。
VBox
Places the nodes in a single column.
将节点放在单个列中。

9.Shapes

● Shapes are nodes used for drawing texts, lines, circles, rectangles, ellipses, arcs, polygons, and polylines; with properties:
○ fill: a color fills the interior of a shape
○ stroke: a color used to draw the outline of a shape
○ strokeWidth: width of outline of a shape

10.Text

(x,y)=(10,100)
Text text3 = new Text(10, 100, "Programming is fun\nDisplay text");
text3.setFil1(Color.RED);//红色
text3.setUnderline(true);下划线
text3.setStrikethrough(true);删除线
pane.getChildren().add(text3);
//在cw3的文字绑定窗口的操作中,并没有使用Text而是label。

11.Line

绑定窗口操作 Line(startX,startY,endX,endY)
pFJD7QI.png

12.Rectangle

//Create rectangles
Rectangle r1 = new Rectangle(25, 10, 60,30);
r1.setFill (Color.WHITE);
r1.setStroke(Color.BLACK);
Rectangle r2 = new Rectangle(25, 50, 60, 30);
Rectangle r3 = new Rectangle(25, 90, 60,30);
r3.setArcWidth(15);
r3.setArcHeight (25);
// Create a group and add nodes to the group
Group group = new Group();
group.getChildren().addA11(new Text(10, 27, "r1"), r1,
new Text(10, 67, "r2"), r2, new Text(10, 107, "r3"), r3);

for (int i= 0; i<4; i++) {
Rectangle r = new Rectangle(100, 50, 100, 30);
r.setRotate(i * 360 / 8);
r.setStroke(Color.color(Math.random(), Math.random(),Math.random()));
r.setFil1 (Color.WHITE);
group.getChildren().add(r);
}

13.Ellipse

Ellipse(centerX,centerY,radiusX,radiusY)
pFJDLef.png

14.Arc

pFJDOw8.png
Arc(centerX,centerY,radiusX,radiusY,startAngle,length)
pFJDXTS.png
Arc.setType

15.Polygon and Polyline

多边形多段线 实际上是List计算和for循环的组合
pFJcU58.png

16.Lab

Task1

制作一个椭圆,尝试添加文字说明
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Polygon;
import javafx.stage.Stage;
public class circle extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) {
Group root = new Group();
Circle circle = new Circle(200, 200, 150);
circle.setStroke(Color.BLACK);
circle.setFill(null);
double radius = circle.getRadius();
double centerX = circle.getCenterX();
double centerY = circle.getCenterY();
double triangleTopX = centerX;
double triangleTopY = centerY - radius;
double triangleLeftX = centerX - (radius * Math.cos(Math.PI / 6));
double triangleLeftY = centerY + (radius * Math.sin(Math.PI / 6));
double triangleRightX = centerX + (radius * Math.cos(Math.PI / 6));
double triangleRightY = centerY + (radius * Math.sin(Math.PI / 6));
Polygon triangle = new Polygon(triangleTopX, triangleTopY, triangleLeftX, triangleLeftY, triangleRightX, triangleRightY);
triangle.setFill(Color.BLUE);
root.getChildren().addAll(circle, triangle);
Scene scene = new Scene(root, 400, 400);
primaryStage.setScene(scene);
primaryStage.setTitle("Triangle Inside Circle");
primaryStage.show();
}
}

Task2

制作一个JavaFX程序,显示两个垂直的长方形,并且使之透明不遮盖,尝试添加文字说明 JAVA FX
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.Font;
import javafx.scene.text.Text;
import javafx.stage.Stage;

public class RectangleAndTextApp extends Application {

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

    @Override
    public void start(Stage primaryStage) {
        Rectangle rectangle1 = new Rectangle(100, 100,40,30);
        Rectangle rectangle2 = new Rectangle(100,100,30,40);
        Text text = new Text("trisla");
        text.setFont(new Font(20));
        text.setX(30);
        text.setY(40);
        rectangle1.setFill(Color.TRANSPARENT);
        rectangle2.setFill(Color.TRANSPARENT);
        rectangle1.setStroke(Color.BLACK);
        rectangle2.setStroke(Color.BLACK);
        Pane root = new Pane();
        root.getChildren().addAll(rectangle1, text,rectangle2);

        Scene scene = new Scene(root, 400, 400);
        primaryStage.setScene(scene);
        primaryStage.show();

        // Bind the rectangle's width and height to the scene's width and height
        rectangle1.widthProperty().bind(scene.widthProperty().divide(3));
        rectangle1.heightProperty().bind(scene.heightProperty().divide(4));
        rectangle2.widthProperty().bind(scene.widthProperty().divide(4));
        rectangle2.heightProperty().bind(scene.heightProperty().divide(3));
        text.xProperty().bind(scene.heightProperty().divide(10));
        text.yProperty().bind(scene.widthProperty().subtract(10));
       
    }
}