引言
- JavaFX是开发JavaGUI程序的新框架
- JavaFX API是演示如何应用面向对象原则的优秀范例
JavaFX与Swing以及AWT的比较
- JavaFX平台取代了Swing和AMT,用于开发富GUI(图形用户界面)应用
- GUI类使用一个称为抽象窗体工具包(AWT)的库
- AWT开发简单的图形用户界面尚可,但是不适合开发综合型的GUI项目,且易受特定于平台的错误的影响
- Swing组件使用Java代码在画布上直接绘制,Swing组件较少依赖目标平台,且使用更少的本地GUI资源,用于开发桌面GUI应用
JavaFX程序的基本结构
-
javafx.application.Application
类定义了编写JavaFX程序的基本框架
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.stage.Stage;
public class MyJavaFX extends Application {
@Override // Override the start method in the Application class
public void start(Stage primaryStage) {
// Create a button and place it in the scene
Button btOK = new Button("OK");
Scene scene = new Scene(btOK, 200, 250);
primaryStage.setTitle("MyJavaFX"); // Set the stage title
primaryStage.setScene(scene); // Place the scene in the stage
primaryStage.show(); // Display the stage
}
/**
* The main method is only needed for the IDE with limited
* JavaFX support. Not needed for running from the command line.
*/
public static void main(String[] args) {
launch(args);
}
}
- 程序说明:
-
lanch
方法是定义一个在Application类中的静态方法,用于启动一个独立的JavaFX应用 - main方法不是必需的
- 一个称为主舞台的Stage对象由JVM自动创建
- 默认情况下,用户可以改变舞台的大小
面板,组,UI组件以及形状
- 面板,组,UI组件以及形状是Node的子类型
- 结点是可视化组件
- 形状是指文本,直线,圆,椭圆,矩形,多边形,弧,折线等
- UI组件是指标签,按钮,复选框,单选按钮,文本域,文本输入,区域等
- 组是将结点集合进行分组的容器
- Scene可以包含Control,Group,或者Pane,但是不能包含Shape或者ImageView
- Pane和Group可以包含Node的任何子类型
- Node的每个子类都有一个无参构造方法,用于创建一个默认的结点
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class ButtonInPane extends Application {
@Override // Override the start method in the Application class
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"));
Scene scene = new Scene(pane, 200, 50);
primaryStage.setTitle("Button in a pane"); // Set the stage title
primaryStage.setScene(scene); // Place the scene in the stage
primaryStage.show(); // Display the stage
}
/**
* The main method is only needed for the IDE with limited
* JavaFX support. Not needed for running from the command line.
*/
public static void main(String[] args) {
launch(args);
}
}
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.stage.Stage;
public class ShowCircle extends Application {
@Override // Override the start method in the Application class
public void start(Stage primaryStage) {
// Create a circle and set its properties
Circle circle = new Circle();
circle.setCenterX(100);
circle.setCenterY(100);
circle.setRadius(50);
circle.setStroke(Color.BLACK);
circle.setFill(Color.RED);
// 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, 200, 200);
primaryStage.setTitle("ShowCircle"); // Set the stage title
primaryStage.setScene(scene); // Place the scene in the stage
primaryStage.show(); // Display the stage
}
/**
* The main method is only needed for the IDE with limited
* JavaFX support. Not needed for running from the command line.
*/
public static void main(String[] args) {
launch(args);
}
}
在Java坐标系中,面板左上角的坐标是(0,0),不同于传统坐标系中(0,0)位于窗体的中央
- 如图,在Java坐标系中,X坐标从左向右递增,Y坐标从上向下递增
面板置于场景中,然后场景置于舞台中
- 可以将一个目标对象绑定到源对象中,源对象的修改将自动反映到目标对象中
- 目标对象称为绑定对象或者绑定属性
- 源对象称为可绑定对象或者可观察对象
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.stage.Stage;
public class ShowCircleCentered extends Application {
@Override // Override the start method in the Application class
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.heightProperty().divide(2));
circle.setRadius(50);
circle.setStroke(Color.BLACK);
circle.setFill(Color.RED);
pane.getChildren().add(circle); // Add circle to the pane
// Create a scene and place it in the stage
Scene scene = new Scene(pane, 200, 200);
primaryStage.setTitle("ShowCircleCentered"); // Set the stage title
primaryStage.setScene(scene); // Place the scene in the stage
primaryStage.show(); // Display the stage
}
/**
* The main method is only needed for the IDE with limited
* JavaFX support. Not needed for running from the command line.
*/
public static void main(String[] args) {
launch(args);
}
}
- 节点具有许多通用的属性
- JavaFX中的样式属性称为JavaFX CSS
- 样式属性使用前缀
-fx-
进行定义 - 每个结点拥有它自己的样式属性
- 设定样式的语法是
styleName:value
- 一个结点的多个样式属性可以一起设置,通过分号;进行分隔
- 如果使用了一个不正确的JavaFX CSS,程序依然可以编译和运行,但是样式将被忽略
rotate
属性可以设定一个以度为单位的角度,让结点围绕它的中心旋转该角度 正顺负逆
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.stage.Stage;
import javafx.scene.layout.StackPane;
public class NodeStyleRotateDemo extends Application {
@Override // Override the start method in the Application class
public void start(Stage primaryStage) {
// Create a scene and place a button in the scene
StackPane pane = new StackPane();
Button btOK = new Button("OK");
btOK.setStyle("-fx-border-color: blue;");
pane.getChildren().add(btOK);
pane.setRotate(45);
pane.setStyle(
"-fx-border-color: red; -fx-background-color: lightgray;");
Scene scene = new Scene(pane, 200, 250);
primaryStage.setTitle("NodeStyleRotateDemo"); // Set the stage title
primaryStage.setScene(scene); // Place the scene in the stage
primaryStage.show(); // Display the stage
}
/**
* The main method is only needed for the IDE with limited
* JavaFX support. Not needed for running from the command line.
*/
public static void main(String[] args) {
launch(args);
}
}
Color类可以用于创建颜色
javafx.scene.paint.Color
子类可以通过以下方法构建color实例:
public Color( double r, double g, double b, double opacity)
- r: 红色 g:绿色 b:蓝色 0.0(最深色) 1.0(最浅色)
- opacity:透明度 0.0(完全透明) 1.0(完全不透明)
- Color类是不可修改的
- Font类描述字体名称,粗细和大小
javafx.scene.text.Font
- Font实例可以用它的构造方法或者静态方法来构建
- Font可以用它的名称,粗细,字形和大小来描述
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.text.*;
import javafx.scene.control.*;
import javafx.stage.Stage;
public class FontDemo extends Application {
@Override // Override the start method in the Application class
public void start(Stage primaryStage) {
// Create a pane to hold the circle
Pane pane = new StackPane();
// Create a circle and set its properties
Circle circle = new Circle();
circle.setRadius(50);
circle.setStroke(Color.BLACK);
circle.setFill(new Color(0.5, 0.5, 0.5, 0.1));
pane.getChildren().add(circle); // Add circle to the pane
// Create a label and set its properties
Label label = new Label("JavaFX");
label.setFont(Font.font("Times New Roman",
FontWeight.BOLD, FontPosture.ITALIC, 20));
pane.getChildren().add(label);
// Create a scene and place it in the stage
Scene scene = new Scene(pane);
primaryStage.setTitle("FontDemo"); // Set the stage title
primaryStage.setScene(scene); // Place the scene in the stage
primaryStage.show(); // Display the stage
}
/**
* The main method is only needed for the IDE with limited
* JavaFX support. Not needed for running from the command line.
*/
public static void main(String[] args) {
launch(args);
}
}
- Font对象是不可改变的
- Image类创建一个图形图像
- ImageView类可以用于显示一个图像
java.scene.image.Image
类表示一个图像,用于从一个指定的文件名或者URL载入一个图像java.scene.image.ImageView
是一个用于显示图像的结点- ImageView可以从一个Image对象创建
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.geometry.Insets;
import javafx.stage.Stage;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
public class ShowImage extends Application {
@Override // Override the start method in the Application class
public void start(Stage primaryStage) {
// Create a pane to hold the image views
Pane pane = new HBox(10);
pane.setPadding(new Insets(5, 5, 5, 5));
Image image = new Image("image/us.gif");
pane.getChildren().add(new ImageView(image));
ImageView imageView2 = new ImageView(image);
imageView2.setFitHeight(100);
imageView2.setFitWidth(100);
pane.getChildren().add(imageView2);
ImageView imageView3 = new ImageView(image);
imageView3.setRotate(90);
pane.getChildren().add(imageView3);
// Create a scene and place it in the stage
Scene scene = new Scene(pane);
primaryStage.setTitle("ShowImage"); // Set the stage title
primaryStage.setScene(scene); // Place the scene in the stage
primaryStage.show(); // Display the stage
}
/**
* The main method is only needed for the IDE with limited
* JavaFX support. Not needed for running from the command line.
*/
public static void main(String[] args) {
launch(args);
}
}
- Image对象可以被多个结点共享
- ImageView这样的结点不能共享,不能讲一个ImageView多次放入一个面板或者场景中
- 注意⚠️:必须将图像文件放在类文件的相同目录中,如下图所示:
- JavaFX提供了多种类型的面板,用于自动地将结点以希望的位置和大小进行布局
- 面板和组是容纳结点的容器
- Group类常用于将结点组合成组并作为一个组进行转换和缩放
- 面板和UI组件对象是可改变大小的
FlowPane(流水面板)
- FlowPane将结点按照加入的顺序,从左到右水平或从上到下垂直组织
- 水平:
Orientation.HORIZONTAL
- 垂直:
Orientation.VERTICAL
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.FlowPane;
import javafx.stage.Stage;
public class ShowFlowPane extends Application {
@Override // Override the start method in the Application class
public void start(Stage primaryStage) {
// Create a pane and set its properties
FlowPane pane = new FlowPane();
pane.setPadding(new Insets(11, 12, 13, 14)); //Insets对象制定了一个面板边框的大小
pane.setHgap(5);
pane.setVgap(5);
// Place nodes in the pane
pane.getChildren().addAll(new Label("First Name:"),
new TextField(), new Label("MI:"));
TextField tfMi = new TextField();
tfMi.setPrefColumnCount(1); //文本域结点
pane.getChildren().addAll(tfMi, new Label("Last Name:"),
new TextField());
// Create a scene and place it in the stage
Scene scene = new Scene(pane, 200, 250);
primaryStage.setTitle("ShowFlowPane"); // Set the stage title
primaryStage.setScene(scene); // Place the scene in the stage
primaryStage.show(); // Display the stage
}
/**
* The main method is only needed for the IDE with limited
* JavaFX support. Not needed for running from the command line.
*/
public static void main(String[] args) {
launch(args);
}
}
- 将一个结点加入一个面板中多次或者不同面板中将引起运行时错误
GridPane(网络面板)
- GridPane将结点安排在一个网格(矩阵)结构中
- 结点放在一个指定下标的列和行中
import javafx.application.Application;
import javafx.geometry.HPos;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;
public class ShowGridPane extends Application {
@Override // Override the start method in the Application class
public void start(Stage primaryStage) {
// Create a pane and set its properties
GridPane pane = new GridPane();
pane.setAlignment(Pos.CENTER); //对齐方式居中
pane.setPadding(new Insets(11.5, 12.5, 13.5, 14.5));
pane.setHgap(5.5);
pane.setVgap(5.5);
// Place nodes in the pane
pane.add(new Label("First Name:"), 0, 0); //标签
pane.add(new TextField(), 1, 0);
pane.add(new Label("MI:"), 0, 1);
pane.add(new TextField(), 1, 1);
pane.add(new Label("Last Name:"), 0, 2);
pane.add(new TextField(), 1, 2);
Button btAdd = new Button("Add Name");
pane.add(btAdd, 1, 3);
GridPane.setHalignment(btAdd, HPos.RIGHT); //调用静态的setHalignment方法将按钮在单元格中右对齐
// Create a scene and place it in the stage
Scene scene = new Scene(pane);
primaryStage.setTitle("ShowGridPane"); // Set the stage title
primaryStage.setScene(scene); // Place the scene in the stage
primaryStage.show(); // Display the stage
}
/**
* The main method is only needed for the IDE with limited
* JavaFX support. Not needed for running from the command line.
*/
public static void main(String[] args) {
launch(args);
}
}
BorderPane(边框面板)
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class ShowBorderPane extends Application {
@Override // Override the start method in the Application class
public void start(Stage primaryStage) {
// Create a border pane
BorderPane pane = new BorderPane();
// Place nodes in the pane
pane.setTop(new CustomPane("Top"));
pane.setRight(new CustomPane("Right"));
pane.setBottom(new CustomPane("Bottom"));
pane.setLeft(new CustomPane("Left"));
pane.setCenter(new CustomPane("Center"));
// Create a scene and place it in the stage
Scene scene = new Scene(pane);
primaryStage.setTitle("ShowBorderPane"); // Set the stage title
primaryStage.setScene(scene); // Place the scene in the stage
primaryStage.show(); // Display the stage
}
public static void main(String[] args) {
launch(args);
}
}
// Define a custom pane to hold a label in the center of the pane
class CustomPane extends StackPane {
public CustomPane(String title) {
getChildren().add(new Label(title));
setStyle("-fx-border-color: red");
setPadding(new Insets(11.5, 12.5, 13.5, 14.5));
}
}
- 一个面板是一个结点,所以一个面板可以加入另外一个面板中
HBox和VBox
- HBox将他的子结点布局在单个水平行中
- VBox将他的子结点布局在单个垂直列中
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
public class ShowHBoxVBox extends Application {
@Override // Override the start method in the Application class
public void start(Stage primaryStage) {
// Create a border pane
BorderPane pane = new BorderPane();
// Place nodes in the pane
pane.setTop(getHBox());
pane.setLeft(getVBox());
// Create a scene and place it in the stage
Scene scene = new Scene(pane);
primaryStage.setTitle("ShowHBoxVBox"); // Set the stage title
primaryStage.setScene(scene); // Place the scene in the stage
primaryStage.show(); // Display the stage
}
private HBox getHBox() {
HBox hBox = new HBox(15);
hBox.setPadding(new Insets(15, 15, 15, 15));
hBox.setStyle("-fx-background-color: gold");
hBox.getChildren().add(new Button("Computer Science"));
hBox.getChildren().add(new Button("Chemistry"));
ImageView imageView = new ImageView(new Image("image/us.gif"));
hBox.getChildren().add(imageView);
return hBox;
}
private VBox getVBox() {
VBox vBox = new VBox(15);
vBox.setPadding(new Insets(15, 5, 5, 5));
vBox.getChildren().add(new Label("Courses"));
Label[] courses = {new Label("CSCI 1301"), new Label("CSCI 1302"),
new Label("CSCI 2410"), new Label("CSCI 3720")};
for (Label course: courses) {
VBox.setMargin(course, new Insets(0, 0, 0, 15));
vBox.getChildren().add(course);
}
return vBox;
}
/**
* The main method is only needed for the IDE with limited
* JavaFX support. Not needed for running from the command line.
*/
public static void main(String[] args) {
launch(args);
}
}
- Shape类是一个抽象基类,定义了所有形状的共同属性
fill
属性指定一个填充形状内部区域的颜色Stroke
属性指定用于绘制形状轮廓的颜色stroekWidth
属性指定形状轮廓的宽度
Text
- Text类定义了一个结点,用于在一个起始点(x,y)处显示一个字符串
- Text对象通常设置在一个面板中
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.geometry.Insets;
import javafx.stage.Stage;
import javafx.scene.text.Text;
import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;
import javafx.scene.text.FontPosture;
public class ShowText extends Application {
@Override // Override the start method in the Application class
public void start(Stage primaryStage) {
// Create a pane to hold the texts
Pane pane = new Pane();
pane.setPadding(new Insets(5, 5, 5, 5));
Text text1 = new Text(20, 20, "Programming is fun");
text1.setFont(Font.font("Courier", FontWeight.BOLD,
FontPosture.ITALIC, 15));
pane.getChildren().add(text1);
Text text2 = new Text(60, 60, "Programming is fun\nDisplay text");
pane.getChildren().add(text2);
Text text3 = new Text(10, 100, "Programming is fun\nDisplay text");
text3.setFill(Color.RED);
text3.setUnderline(true);
text3.setStrikethrough(true);
pane.getChildren().add(text3);
// Create a scene and place it in the stage
Scene scene = new Scene(pane);
primaryStage.setTitle("ShowText"); // Set the stage title
primaryStage.setScene(scene); // Place the scene in the stage
primaryStage.show(); // Display the stage
}
/**
* The main method is only needed for the IDE with limited
* JavaFX support. Not needed for running from the command line.
*/
public static void main(String[] args) {
launch(args);
}
}