当前位置: 首页 > news >正文

《Java 程序设计》第 14 章 - JavaFX 基础

        大家好!今天我们来学习《Java 程序设计》中的第 14 章 ——JavaFX 基础。JavaFX 是用于构建富互联网应用程序的 Java 库,它提供了一套完整的图形界面(GUI)工具包,让我们能够创建美观、交互性强的桌面应用。本章将从 JavaFX 的基本概念讲起,逐步深入到布局、控件、特效等内容,并通过丰富的代码示例帮助大家快速上手。

思维导图

14.1 JavaFX 概述

14.1.1 Java GUI 编程简史

Java 的 GUI 编程发展经历了几个重要阶段:

  1. AWT(Abstract Window Toolkit):Java 最早的 GUI 工具包,依赖于底层操作系统的 GUI 组件,跨平台性有限,外观在不同系统上差异较大。
  2. Swing:纯 Java 实现的 GUI 工具包,不依赖底层操作系统,真正实现了跨平台的统一外观,提供了更丰富的组件。
  3. JavaFX:作为 Swing 的继任者,提供了更现代、更强大的 GUI 编程能力,支持 2D/3D 图形、动画、多媒体等,采用了 MVC 架构,更适合构建复杂的富客户端应用。

14.1.2 JavaFX 基本概念

JavaFX 引入了一些核心概念:

  • 舞台(Stage):代表应用程序的窗口,是 JavaFX 应用的顶级容器。
  • 场景(Scene):包含在舞台中,是所有 UI 元素的容器。一个舞台可以切换多个场景。
  • 场景图(Scene Graph):由节点(Node)组成的树形结构,代表了应用程序的所有 UI 元素。
  • 节点(Node):场景图中的基本元素,可以是控件、形状、图像等,分为可视节点容器节点

14.1.3 添加 JavaFX 软件包

在 Java 8 到 Java 10 中,JavaFX 是 JDK 的一部分。但从 Java 11 开始,JavaFX 被从 JDK 中分离出来,成为一个独立的库。

添加 JavaFX 的方法

  1. 手动下载:从OpenJFX 官网下载对应版本的 JavaFX SDK,然后在项目中添加库引用。
  2. Maven/Gradle 依赖:在项目的 pom.xml(Maven)或 build.gradle(Gradle)中添加 JavaFX 的依赖。

Maven 配置示例

<dependencies><dependency><groupId>org.openjfx</groupId><artifactId>javafx-controls</artifactId><version>17.0.2</version></dependency><dependency><groupId>org.openjfx</groupId><artifactId>javafx-fxml</artifactId><version>17.0.2</version></dependency>
</dependencies><build><plugins><plugin><groupId>org.openjfx</groupId><artifactId>javafx-maven-plugin</artifactId><version>0.0.8</version><configuration><mainClass>com.example.Main</mainClass></configuration></plugin></plugins>
</build>

14.2 JavaFX 程序基本结构

14.2.1 舞台和场景

  • Stage:JavaFX 应用程序的主窗口,由 JavaFX 系统创建,我们通常在 start () 方法中接收这个舞台对象并进行设置。
  • Scene:场景包含了所有的 UI 元素,需要设置场景的根节点、宽度和高度,然后通过 stage.setScene () 方法将场景设置到舞台上。

14.2.2 场景图和节点

场景图(Scene Graph) 是一个树状结构,由各种节点组成,它是 JavaFX 应用程序的视觉呈现。场景图的每个元素都是一个节点(Node)

节点分为两类:

  • 可视节点:如按钮(Button)、文本(Text)、形状(Shape)等,能够在界面上显示。
  • 容器节点:如面板(Pane),用于组织和布局其他节点。

14.2.3 Application 类生命周期方法

JavaFX 应用程序需要继承 Application 类,并重写其生命周期方法:

  1. init():初始化方法,在应用程序启动时调用,在 start () 方法之前执行,通常用于初始化资源
  2. start(Stage primaryStage):应用程序的主要入口点,在这里创建 UI 并展示舞台,是必须重写的方法。
  3. stop():在应用程序关闭时调用,通常用于释放资源

生命周期流程图

14.2.4 JavaFX 程序启动

JavaFX 程序的启动有两种方式:

  1. 通过 main 方法启动:在 main 方法中调用 Application.launch ()
  2. 直接运行 Application 子类:许多 IDE 支持直接运行继承自 Application 的类,自动调用 launch () 方法。

示例代码:第一个 JavaFX 程序

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;public class FirstJavaFXApp extends Application {// 程序入口点public static void main(String[] args) {// 启动JavaFX应用launch(args);}// 初始化方法@Overridepublic void init() throws Exception {super.init();System.out.println("应用程序初始化中...");}// 启动方法,设置UI并显示舞台@Overridepublic void start(Stage primaryStage) {// 创建一个标签Label label = new Label("Hello, JavaFX!");// 创建一个布局面板,并将标签添加到面板中StackPane root = new StackPane();root.getChildren().add(label);// 创建场景,设置根节点和尺寸Scene scene = new Scene(root, 300, 200);// 设置舞台标题primaryStage.setTitle("我的第一个JavaFX应用");// 设置舞台的场景primaryStage.setScene(scene);// 显示舞台primaryStage.show();}// 停止方法@Overridepublic void stop() throws Exception {super.stop();System.out.println("应用程序正在关闭...");}
}

        运行上述代码,会显示一个窗口,中间有 "Hello, JavaFX!" 的文字。这个简单的程序展示了 JavaFX 应用的基本结构:创建 UI 元素,将它们组织到布局中,创建场景并设置到舞台上,最后显示舞台。

14.3 JavaFX 属性与绑定

14.3.1 JavaFX 属性

        JavaFX 引入了一种新的属性机制,与普通的 Java 字段不同,JavaFX 属性可以被观察和绑定。这意味着当属性的值发生变化时,依赖该属性的其他对象可以自动得到通知并做出相应的处理。

JavaFX 为基本数据类型提供了对应的属性类:

  • IntegerProperty
  • DoubleProperty
  • BooleanProperty
  • StringProperty
  • 等等

示例:JavaFX 属性的使用

import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;public class PropertyExample {public static void main(String[] args) {// 创建一个整数属性IntegerProperty number = new SimpleIntegerProperty(10);// 打印初始值System.out.println("初始值: " + number.get());// 添加监听器,当属性值变化时触发number.addListener((observable, oldValue, newValue) -> {System.out.println("值从 " + oldValue + " 变为 " + newValue);});// 修改属性值number.set(20);number.setValue(30); // 与set()方法效果相同// 通过绑定获取属性值System.out.println("当前值: " + number.getValue());}
}

14.3.2 属性绑定

        属性绑定允许我们将一个属性与另一个属性或表达式关联起来,当被绑定的属性发生变化时,绑定的属性会自动更新。

JavaFX 提供了两种主要的绑定方式:

  • 单向绑定:一个属性的值跟随另一个属性的值变化,但反之则不成立。
  • 双向绑定:两个属性的值相互影响,任何一个的变化都会导致另一个也发生变化。

示例:属性绑定

import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.Slider;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;public class BindingExample extends Application {@Overridepublic void start(Stage primaryStage) {// 创建两个数值属性DoubleProperty a = new SimpleDoubleProperty(10);DoubleProperty b = new SimpleDoubleProperty(20);// 单向绑定:c的值始终是a + bDoubleProperty c = new SimpleDoubleProperty();c.bind(a.add(b));System.out.println("a = " + a.get() + ", b = " + b.get() + ", c = " + c.get());// 修改a的值,c的值会自动更新a.set(15);System.out.println("a = " + a.get() + ", b = " + b.get() + ", c = " + c.get());// 修改b的值,c的值会自动更新b.set(25);System.out.println("a = " + a.get() + ", b = " + b.get() + ", c = " + c.get());// 创建UI演示绑定效果Slider slider = new Slider(0, 100, 50);Label label = new Label();// 将标签的文本绑定到滑块的值label.textProperty().bind(Bindings.format("滑块值: %.2f", slider.valueProperty()));VBox root = new VBox(10);root.getChildren().addAll(slider, label);Scene scene = new Scene(root, 300, 100);primaryStage.setTitle("属性绑定示例");primaryStage.setScene(scene);primaryStage.show();}public static void main(String[] args) {launch(args);}
}

        运行上述代码,会显示一个滑块和一个标签。当拖动滑块时,标签的文本会实时显示滑块的当前值,这就是属性绑定的效果。

14.4 JavaFX 界面布局

14.4.1 JavaFX 坐标系

JavaFX 使用二维坐标系来定位节点

  • 原点 (0, 0) 位于左上角
  • X 轴向右为正方向
  • Y 轴向下为正方向
  • 坐标单位为像素

14.4.2 Pane 面板

        Pane 是最简单的布局面板,它不对子节点进行任何布局管理,子节点的位置需要通过设置其 layoutX 和 layoutY 属性来指定。

示例:Pane 面板的使用

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;public class PaneExample extends Application {@Overridepublic void start(Stage primaryStage) {Pane pane = new Pane();// 创建按钮并设置位置Button btn1 = new Button("按钮1");btn1.setLayoutX(20);  // X坐标btn1.setLayoutY(30);  // Y坐标Button btn2 = new Button("按钮2");btn2.setLayoutX(120);btn2.setLayoutY(80);// 将按钮添加到面板pane.getChildren().addAll(btn1, btn2);Scene scene = new Scene(pane, 300, 200);primaryStage.setTitle("Pane面板示例");primaryStage.setScene(scene);primaryStage.show();}public static void main(String[] args) {launch(args);}
}

14.4.3 HBox 面板

HBox(水平盒)面板将子节点在水平方向上排列

示例:HBox 面板的使用

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;public class HBoxExample extends Application {@Overridepublic void start(Stage primaryStage) {// 创建HBox面板,设置子节点之间的间距为10像素HBox hbox = new HBox(10);// 设置内边距(上、右、下、左)hbox.setPadding(new Insets(10, 10, 10, 10));// 创建按钮Button btn1 = new Button("按钮1");Button btn2 = new Button("按钮2");Button btn3 = new Button("按钮3");// 将按钮添加到HBoxhbox.getChildren().addAll(btn1, btn2, btn3);Scene scene = new Scene(hbox, 300, 100);primaryStage.setTitle("HBox面板示例");primaryStage.setScene(scene);primaryStage.show();}public static void main(String[] args) {launch(args);}
}

14.4.4 VBox 面板

VBox(垂直盒)面板将子节点在垂直方向上排列

示例:VBox 面板的使用

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;public class VBoxExample extends Application {@Overridepublic void start(Stage primaryStage) {// 创建VBox面板,设置子节点之间的间距为10像素VBox vbox = new VBox(10);// 设置内边距vbox.setPadding(new Insets(10));// 创建按钮Button btn1 = new Button("按钮1");Button btn2 = new Button("按钮2");Button btn3 = new Button("按钮3");// 将按钮添加到VBoxvbox.getChildren().addAll(btn1, btn2, btn3);Scene scene = new Scene(vbox, 150, 200);primaryStage.setTitle("VBox面板示例");primaryStage.setScene(scene);primaryStage.show();}public static void main(String[] args) {launch(args);}
}

14.4.5 BorderPane 面板

        BorderPane 将容器分为 5 个区域:上(top)、下(bottom)、左(left)、右(right)和中心(center),分别用于放置不同的子节点。

示例:BorderPane 面板的使用

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;public class BorderPaneExample extends Application {@Overridepublic void start(Stage primaryStage) {BorderPane borderPane = new BorderPane();// 设置内边距borderPane.setPadding(new Insets(10));// 创建各个区域的按钮Button topBtn = new Button("顶部");Button bottomBtn = new Button("底部");Button leftBtn = new Button("左侧");Button rightBtn = new Button("右侧");Button centerBtn = new Button("中心");// 将按钮放置到BorderPane的对应区域borderPane.setTop(topBtn);borderPane.setBottom(bottomBtn);borderPane.setLeft(leftBtn);borderPane.setRight(rightBtn);borderPane.setCenter(centerBtn);Scene scene = new Scene(borderPane, 400, 300);primaryStage.setTitle("BorderPane面板示例");primaryStage.setScene(scene);primaryStage.show();}public static void main(String[] args) {launch(args);}
}

14.4.6 FlowPane 面板

        FlowPane 会根据面板的大小自动排列子节点,当一行(或一列)放不下时,会自动换行(或换列)。默认是水平流动,也可以设置为垂直流动。

示例:FlowPane 面板的使用

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.FlowPane;
import javafx.stage.Stage;public class FlowPaneExample extends Application {@Overridepublic void start(Stage primaryStage) {// 创建FlowPane,设置水平方向流动,水平和垂直间距都是10FlowPane flowPane = new FlowPane(10, 10);// 设置内边距flowPane.setPadding(new Insets(10));// 创建多个按钮for (int i = 1; i <= 10; i++) {flowPane.getChildren().add(new Button("按钮 " + i));}Scene scene = new Scene(flowPane, 300, 200);primaryStage.setTitle("FlowPane面板示例");primaryStage.setScene(scene);primaryStage.show();}public static void main(String[] args) {launch(args);}
}

        运行程序后,尝试调整窗口大小,会看到按钮会根据窗口宽度自动重新排列

14.4.7 GridPane 面板

        GridPane(网格面板)将容器划分为行和列的网格,子节点可以放置在指定的单元格中,也可以跨多行或多列。

示例:GridPane 面板的使用

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;public class GridPaneExample extends Application {@Overridepublic void start(Stage primaryStage) {GridPane gridPane = new GridPane();// 设置内边距gridPane.setPadding(new Insets(10));// 设置行列间距gridPane.setHgap(5);  // 水平间距gridPane.setVgap(5);  // 垂直间距// 创建按钮并放置到网格的指定位置for (int row = 0; row < 3; row++) {for (int col = 0; col < 3; col++) {Button btn = new Button("(" + row + "," + col + ")");// 将按钮添加到网格的第row行,第col列GridPane.setRowIndex(btn, row);GridPane.setColumnIndex(btn, col);gridPane.getChildren().add(btn);}}// 创建一个跨列的按钮Button wideBtn = new Button("跨两列");GridPane.setRowIndex(wideBtn, 3);GridPane.setColumnIndex(wideBtn, 0);// 设置跨2列GridPane.setColumnSpan(wideBtn, 2);gridPane.getChildren().add(wideBtn);Scene scene = new Scene(gridPane, 300, 250);primaryStage.setTitle("GridPane面板示例");primaryStage.setScene(scene);primaryStage.show();}public static void main(String[] args) {launch(args);}
}

14.4.8 StackPane 面板

        StackPane(栈面板)将子节点堆叠在一起,默认情况下,所有子节点都居中对齐。后添加的节点会覆盖在先添加的节点上面。

示例:StackPane 面板的使用

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;public class StackPaneExample extends Application {@Overridepublic void start(Stage primaryStage) {StackPane stackPane = new StackPane();// 创建一个圆形作为背景Circle circle = new Circle(100);circle.setFill(Color.LIGHTBLUE);// 创建一个标签Label label = new Label("我在圆形上面");label.setTextFill(Color.DARKBLUE);// 添加到栈面板,先添加的在下面,后添加的在上面stackPane.getChildren().addAll(circle, label);Scene scene = new Scene(stackPane, 300, 300);primaryStage.setTitle("StackPane面板示例");primaryStage.setScene(scene);primaryStage.show();}public static void main(String[] args) {launch(args);}
}

14.4.9 AnchorPane 面板

        AnchorPane(锚点面板)允许子节点锚定到面板的边缘或中心,可以设置子节点与面板边缘的距离。

示例:AnchorPane 面板的使用

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;public class AnchorPaneExample extends Application {@Overridepublic void start(Stage primaryStage) {AnchorPane anchorPane = new AnchorPane();// 创建按钮Button topLeftBtn = new Button("左上");Button topRightBtn = new Button("右上");Button bottomLeftBtn = new Button("左下");Button bottomRightBtn = new Button("右下");Button centerBtn = new Button("居中");// 设置按钮的锚点// 左上按钮:锚定到顶部和左侧AnchorPane.setTopAnchor(topLeftBtn, 10.0);AnchorPane.setLeftAnchor(topLeftBtn, 10.0);// 右上按钮:锚定到顶部和右侧AnchorPane.setTopAnchor(topRightBtn, 10.0);AnchorPane.setRightAnchor(topRightBtn, 10.0);// 左下按钮:锚定到底部和左侧AnchorPane.setBottomAnchor(bottomLeftBtn, 10.0);AnchorPane.setLeftAnchor(bottomLeftBtn, 10.0);// 右下按钮:锚定到底部和右侧AnchorPane.setBottomAnchor(bottomRightBtn, 10.0);AnchorPane.setRightAnchor(bottomRightBtn, 10.0);// 居中按钮:同时设置左右和上下锚点,会自动居中AnchorPane.setLeftAnchor(centerBtn, 100.0);AnchorPane.setRightAnchor(centerBtn, 100.0);AnchorPane.setTopAnchor(centerBtn, 100.0);AnchorPane.setBottomAnchor(centerBtn, 100.0);// 添加按钮到面板anchorPane.getChildren().addAll(topLeftBtn, topRightBtn, bottomLeftBtn, bottomRightBtn, centerBtn);Scene scene = new Scene(anchorPane, 300, 250);primaryStage.setTitle("AnchorPane面板示例");primaryStage.setScene(scene);primaryStage.show();}public static void main(String[] args) {launch(args);}
}

14.4.10 使用 CSS 设置控件样式

JavaFX 支持使用 CSS(层叠样式表)来设置控件的外观,这使得界面美化更加灵活和高效。

示例:使用 CSS 设置控件样式

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;public class CSSExample extends Application {@Overridepublic void start(Stage primaryStage) {VBox root = new VBox(10);root.setStyle("-fx-padding: 20; -fx-background-color: #f0f0f0;");// 创建按钮Button btn1 = new Button("普通按钮");// 直接设置样式btn1.setStyle("-fx-font-size: 14px; -fx-padding: 8px 16px;");Button btn2 = new Button("带样式类的按钮");// 添加样式类btn2.getStyleClass().add("custom-button");Button btn3 = new Button("悬停效果按钮");btn3.getStyleClass().add("hover-button");root.getChildren().addAll(btn1, btn2, btn3);Scene scene = new Scene(root, 300, 200);// 添加CSS样式表scene.getStylesheets().add(getClass().getResource("style.css").toExternalForm());primaryStage.setTitle("CSS样式示例");primaryStage.setScene(scene);primaryStage.show();}public static void main(String[] args) {launch(args);}
}

在项目的相同包下创建一个名为style.css的文件,内容如下:

/* 自定义按钮样式 */
.custom-button {-fx-background-color: #4CAF50; /* 绿色背景 */-fx-text-fill: white; /* 白色文字 */-fx-font-size: 14px;-fx-padding: 8px 16px;-fx-border-radius: 4px;
}/* 悬停效果按钮 */
.hover-button {-fx-background-color: #2196F3; /* 蓝色背景 */-fx-text-fill: white;-fx-font-size: 14px;-fx-padding: 8px 16px;-fx-border-radius: 4px;-fx-transition: all 0.3s ease;
}/* 鼠标悬停时的样式 */
.hover-button:hover {-fx-background-color: #0b7dda; /* 深蓝色背景 */-fx-scale-x: 1.05;-fx-scale-y: 1.05;
}

布局面板综合案例

下面是一个综合使用多种布局面板的案例,模拟一个简单的应用程序界面:

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.stage.Stage;public class Layout综合案例 extends Application {@Overridepublic void start(Stage primaryStage) {// 主面板使用BorderPaneBorderPane mainPane = new BorderPane();mainPane.setPadding(new Insets(10));// 顶部:标题栏HBox topBar = new HBox();topBar.setPadding(new Insets(10));topBar.setStyle("-fx-background-color: #336699;");Label titleLabel = new Label("我的应用程序");titleLabel.setStyle("-fx-text-fill: white; -fx-font-size: 18px; -fx-font-weight: bold;");topBar.getChildren().add(titleLabel);mainPane.setTop(topBar);// 左侧:导航菜单VBox leftNav = new VBox(10);leftNav.setPadding(new Insets(10));leftNav.setStyle("-fx-background-color: #f0f0f0;");leftNav.setPrefWidth(150);Button homeBtn = new Button("首页");Button dataBtn = new Button("数据管理");Button settingBtn = new Button("设置");Button helpBtn = new Button("帮助");// 设置按钮宽度为100%homeBtn.setMaxWidth(Double.MAX_VALUE);dataBtn.setMaxWidth(Double.MAX_VALUE);settingBtn.setMaxWidth(Double.MAX_VALUE);helpBtn.setMaxWidth(Double.MAX_VALUE);leftNav.getChildren().addAll(homeBtn, dataBtn, settingBtn, helpBtn);mainPane.setLeft(leftNav);// 中心:主要内容区域,使用GridPaneGridPane contentPane = new GridPane();contentPane.setPadding(new Insets(20));contentPane.setHgap(10);contentPane.setVgap(15);// 添加标题Label contentTitle = new Label("用户信息");contentTitle.setStyle("-fx-font-size: 16px; -fx-font-weight: bold;");GridPane.setColumnSpan(contentTitle, 2); // 跨两列contentPane.add(contentTitle, 0, 0);// 添加表单控件Label nameLabel = new Label("姓名:");TextField nameField = new TextField();Label ageLabel = new Label("年龄:");TextField ageField = new TextField();Label genderLabel = new Label("性别:");HBox genderBox = new HBox(10);RadioButton maleBtn = new RadioButton("男");RadioButton femaleBtn = new RadioButton("女");ToggleGroup genderGroup = new ToggleGroup();maleBtn.setToggleGroup(genderGroup);femaleBtn.setToggleGroup(genderGroup);maleBtn.setSelected(true);genderBox.getChildren().addAll(maleBtn, femaleBtn);Label hobbyLabel = new Label("爱好:");VBox hobbyBox = new VBox(5);CheckBox readingBox = new CheckBox("阅读");CheckBox sportsBox = new CheckBox("运动");CheckBox musicBox = new CheckBox("音乐");hobbyBox.getChildren().addAll(readingBox, sportsBox, musicBox);// 放置控件到网格中contentPane.add(nameLabel, 0, 1);contentPane.add(nameField, 1, 1);contentPane.add(ageLabel, 0, 2);contentPane.add(ageField, 1, 2);contentPane.add(genderLabel, 0, 3);contentPane.add(genderBox, 1, 3);contentPane.add(hobbyLabel, 0, 4);contentPane.add(hobbyBox, 1, 4);// 添加按钮区域,使用HBoxHBox buttonBox = new HBox(10);Button saveBtn = new Button("保存");Button cancelBtn = new Button("取消");saveBtn.setStyle("-fx-background-color: #4CAF50; -fx-text-fill: white;");cancelBtn.setStyle("-fx-background-color: #f44336; -fx-text-fill: white;");buttonBox.getChildren().addAll(saveBtn, cancelBtn);GridPane.setColumnSpan(buttonBox, 2);contentPane.add(buttonBox, 0, 5);mainPane.setCenter(contentPane);// 底部:状态栏HBox statusBar = new HBox();statusBar.setPadding(new Insets(5));statusBar.setStyle("-fx-background-color: #e0e0e0; -fx-font-size: 12px;");Label statusLabel = new Label("当前用户: admin | 版本: 1.0.0");statusBar.getChildren().add(statusLabel);mainPane.setBottom(statusBar);Scene scene = new Scene(mainPane, 800, 500);primaryStage.setTitle("布局综合案例");primaryStage.setScene(scene);primaryStage.show();}public static void main(String[] args) {launch(args);}
}

14.5 Color 和 Font 类

14.5.1 Color 类

Color 类用于表示颜色,可以通过多种方式创建颜色:

  • 使用预定义的颜色常量(如 Color.RED, Color.BLUE)
  • 使用 RGB 值(红、绿、蓝)
  • 使用 RGBA 值(红、绿、蓝、透明度)
  • 使用 HSB 值(色相、饱和度、亮度)

14.5.2 Font 类

Font 类用于表示字体,可以设置字体名称、大小和样式(如粗体、斜体)。

示例:Color 和 Font 类的使用

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;
import javafx.scene.text.FontStyle;
import javafx.stage.Stage;public class ColorAndFontExample extends Application {@Overridepublic void start(Stage primaryStage) {VBox root = new VBox(20);root.setPadding(new Insets(20));// 1. 使用预定义颜色和默认字体Label label1 = new Label("1. 红色文本(默认字体)");label1.setTextFill(Color.RED);// 2. 使用RGB颜色和指定字体Label label2 = new Label("2. 蓝色文本(Arial字体,16号)");label2.setTextFill(new Color(0, 0, 1, 1)); // RGBA,最后一个参数是透明度label2.setFont(new Font("Arial", 16));// 3. 使用HSB颜色和粗体字体Label label3 = new Label("3. 绿色文本(粗体,18号)");label3.setTextFill(Color.hsb(120, 1, 0.8)); // HSB颜色label3.setFont(Font.font("SimSun", FontWeight.BOLD, 18));// 4. 使用半透明颜色和斜体字体Label label4 = new Label("4. 紫色文本(斜体,20号,半透明)");label4.setTextFill(new Color(0.5, 0, 0.5, 0.7)); // 半透明紫色label4.setFont(Font.font("Times New Roman", FontStyle.ITALIC, 20));root.getChildren().addAll(label1, label2, label3, label4);Scene scene = new Scene(root, 400, 300);// 设置背景颜色scene.setFill(new Color(0.95, 0.95, 0.95, 1));primaryStage.setTitle("Color和Font示例");primaryStage.setScene(scene);primaryStage.show();}public static void main(String[] args) {launch(args);}
}

14.6 JavaFX 形状

JavaFX 提供了多种预定义的形状类,可以用来绘制各种图形

14.6.1 Line 类

Line 类用于绘制直线,需要指定起点和终点坐标

14.6.2 Rectangle 类

Rectangle 类用于绘制矩形,可以指定位置、宽度、高度,还可以设置圆角

14.6.3 Circle 类

Circle 类用于绘制圆形,需要指定圆心坐标和半径

14.6.4 Ellipse 类

Ellipse 类用于绘制椭圆,需要指定中心坐标和 x、y 方向的半径

14.6.5 Arc 类

Arc 类用于绘制圆弧,需要指定中心坐标、半径、起始角度和弧长

14.6.6 Polygon 类

Polygon 类用于绘制多边形,需要指定多个顶点的坐标

14.6.7 Text 类

Text 类用于绘制文本,可以设置字体、颜色等属性。

示例:各种形状的使用

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.*;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.stage.Stage;public class ShapesExample extends Application {@Overridepublic void start(Stage primaryStage) {Pane pane = new Pane();// 1. 直线Line line = new Line(50, 50, 250, 50);line.setStroke(Color.BLACK);line.setStrokeWidth(2);// 2. 矩形Rectangle rect = new Rectangle(50, 70, 200, 60); // x, y, width, heightrect.setFill(Color.LIGHTBLUE);rect.setStroke(Color.BLUE);rect.setStrokeWidth(2);rect.setArcWidth(10); // 圆角宽度rect.setArcHeight(10); // 圆角高度// 3. 圆形Circle circle = new Circle(150, 220, 40); // centerX, centerY, radiuscircle.setFill(Color.PINK);circle.setStroke(Color.RED);circle.setStrokeWidth(2);// 4. 椭圆Ellipse ellipse = new Ellipse(150, 320, 80, 40); // centerX, centerY, radiusX, radiusYellipse.setFill(Color.LIGHTGREEN);ellipse.setStroke(Color.GREEN);ellipse.setStrokeWidth(2);// 5. 圆弧Arc arc = new Arc(150, 420, 60, 40, 0, 180); // centerX, centerY, radiusX, radiusY, startAngle, lengtharc.setFill(Color.YELLOW);arc.setStroke(Color.ORANGE);arc.setStrokeWidth(2);arc.setType(ArcType.OPEN); // 圆弧类型:OPEN, CHORD, ROUND// 6. 多边形(五角星)Polygon polygon = new Polygon();polygon.getPoints().addAll(300.0, 100.0,320.0, 160.0,380.0, 160.0,330.0, 200.0,350.0, 260.0,300.0, 230.0,250.0, 260.0,270.0, 200.0,220.0, 160.0,280.0, 160.0);polygon.setFill(Color.PURPLE);polygon.setStroke(Color.DARKVIOLET);polygon.setStrokeWidth(2);// 7. 文本Text text = new Text(250, 320, "JavaFX形状");text.setFont(Font.font("SimHei", 20));text.setFill(Color.BROWN);// 将所有形状添加到面板pane.getChildren().addAll(line, rect, circle, ellipse, arc, polygon, text);Scene scene = new Scene(pane, 450, 500);scene.setFill(Color.WHITE);primaryStage.setTitle("JavaFX形状示例");primaryStage.setScene(scene);primaryStage.show();}public static void main(String[] args) {launch(args);}
}

14.7 Image 和 ImageView 类

        JavaFX 提供了 Image 和 ImageView 类来处理和显示图像。Image 类用于加载图像数据,ImageView 类用于在界面上显示图像。

示例:Image 和 ImageView 类的使用

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;public class ImageExample extends Application {@Overridepublic void start(Stage primaryStage) {HBox root = new HBox(20);root.setPadding(new Insets(20));try {// 1. 加载本地图片// 假设图片文件位于项目的resources目录下Image localImage = new Image(getClass().getResourceAsStream("/image1.jpg"));ImageView localImageView = new ImageView(localImage);// 设置图片视图的尺寸,保持比例localImageView.setFitWidth(200);localImageView.setPreserveRatio(true);// 2. 加载网络图片Image networkImage = new Image("https://picsum.photos/200/300");ImageView networkImageView = new ImageView(networkImage);// 3. 调整图片视图的属性ImageView scaledImageView = new ImageView(localImage);scaledImageView.setFitWidth(150);scaledImageView.setFitHeight(150);scaledImageView.setPreserveRatio(false); // 不保持比例,可能会变形scaledImageView.setOpacity(0.7); // 设置透明度root.getChildren().addAll(localImageView, networkImageView, scaledImageView);} catch (Exception e) {e.printStackTrace();System.out.println("图片加载失败: " + e.getMessage());}Scene scene = new Scene(root, 650, 350);primaryStage.setTitle("Image和ImageView示例");primaryStage.setScene(scene);primaryStage.show();}public static void main(String[] args) {launch(args);}
}

        注意:加载本地图片时,需要确保图片文件的路径正确。如果使用 IDE(如 IntelliJ IDEA 或 Eclipse),通常将图片放在src/main/resources目录下,然后使用getClass().getResourceAsStream()方法加载

14.8 特效实现

JavaFX 提供了多种特效类,可以为节点添加各种视觉效果

14.8.1 阴影效果

DropShadow 类用于为节点添加阴影效果。

14.8.2 模糊效果

BlurEffect 类用于为节点添加模糊效果,有高斯模糊、运动模糊等类型。

14.8.3 倒影效果

Reflection 类用于为节点添加倒影效果。

14.8.4 发光效果

Glow 类用于为节点添加发光效果。

示例:各种特效的使用

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.effect.*;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.stage.Stage;public class EffectsExample extends Application {@Overridepublic void start(Stage primaryStage) {HBox root = new HBox(30);root.setStyle("-fx-padding: 30; -fx-background-color: #f0f0f0;");// 1. 阴影效果VBox shadowBox = new VBox(20);Label shadowLabel = new Label("阴影效果");shadowLabel.setFont(Font.font(20));// 创建阴影效果DropShadow dropShadow = new DropShadow();dropShadow.setColor(Color.GRAY);dropShadow.setRadius(10);dropShadow.setOffsetX(5);dropShadow.setOffsetY(5);shadowLabel.setEffect(dropShadow);// 给图片添加阴影ImageView shadowImage = new ImageView(new Image("https://picsum.photos/200/150?random=1"));shadowImage.setEffect(dropShadow);shadowBox.getChildren().addAll(shadowLabel, shadowImage);// 2. 模糊效果VBox blurBox = new VBox(20);Label blurLabel = new Label("模糊效果");blurLabel.setFont(Font.font(20));// 创建高斯模糊效果GaussianBlur gaussianBlur = new GaussianBlur(8); // 模糊半径blurLabel.setEffect(gaussianBlur);ImageView blurImage = new ImageView(new Image("https://picsum.photos/200/150?random=2"));blurImage.setEffect(gaussianBlur);blurBox.getChildren().addAll(blurLabel, blurImage);// 3. 倒影效果VBox reflectionBox = new VBox(20);Label reflectionLabel = new Label("倒影效果");reflectionLabel.setFont(Font.font(20));// 创建倒影效果Reflection reflection = new Reflection();reflection.setFraction(0.8); // 倒影比例reflectionLabel.setEffect(reflection);ImageView reflectionImage = new ImageView(new Image("https://picsum.photos/200/150?random=3"));reflectionImage.setEffect(reflection);reflectionBox.getChildren().addAll(reflectionLabel, reflectionImage);// 4. 发光效果VBox glowBox = new VBox(20);Label glowLabel = new Label("发光效果");glowLabel.setFont(Font.font(20));glowLabel.setTextFill(Color.BLUE);// 创建发光效果Glow glow = new Glow(0.8); // 发光强度glowLabel.setEffect(glow);ImageView glowImage = new ImageView(new Image("https://picsum.photos/200/150?random=4"));glowImage.setEffect(glow);glowBox.getChildren().addAll(glowLabel, glowImage);root.getChildren().addAll(shadowBox, blurBox, reflectionBox, glowBox);Scene scene = new Scene(root, 900, 300);primaryStage.setTitle("JavaFX特效示例");primaryStage.setScene(scene);primaryStage.show();}public static void main(String[] args) {launch(args);}
}

14.9 小结

本章介绍了 JavaFX 的基础知识,包括:

  • JavaFX 概述:了解了 Java GUI 编程的发展历史,JavaFX 的基本概念和如何添加 JavaFX 库。
  • JavaFX 程序基本结构:学习了舞台(Stage)、场景(Scene)、场景图(Scene Graph)和节点(Node)的概念,以及 Application 类的生命周期。
  • JavaFX 属性与绑定:掌握了 JavaFX 属性的特点和绑定机制,能够实现属性之间的自动同步。
  • JavaFX 界面布局:学习了多种布局面板的使用,包括 Pane、HBox、VBox、BorderPane 等,能够根据需要选择合适的布局。
  • Color 和 Font 类:了解了如何使用 Color 类设置颜色,使用 Font 类设置字体
  • JavaFX 形状:学习了如何绘制各种基本形状,如直线、矩形、圆形等。
  • Image 和 ImageView 类:掌握了加载和显示图像的方法
  • 特效实现:了解了如何为节点添加阴影、模糊、倒影和发光等特效

        通过本章的学习,我们已经掌握了 JavaFX 的基础知识,能够创建简单的 JavaFX 应用程序。JavaFX 提供了丰富的 API 和组件,能够帮助我们开发出美观、交互性强的桌面应用。

编程练习

  1. 练习 1:创建一个简单的计算器界面
    要求:使用 GridPane 布局,创建一个包含数字键和基本运算符的计算器界面。

练习 1 参考代码:

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;public class Calculator练习 extends Application {@Overridepublic void start(Stage primaryStage) {GridPane grid = new GridPane();grid.setPadding(new Insets(10));grid.setHgap(5);grid.setVgap(5);// 创建显示框TextField display = new TextField();display.setEditable(false);display.setAlignment(javafx.geometry.Pos.CENTER_RIGHT);display.setStyle("-fx-font-size: 18px;");GridPane.setColumnSpan(display, 4); // 跨4列grid.add(display, 0, 0);// 按钮文本String[][] buttons = {{"7", "8", "9", "/"},{"4", "5", "6", "*"},{"1", "2", "3", "-"},{"0", ".", "=", "+"}};// 创建清除按钮Button clearBtn = new Button("C");clearBtn.setStyle("-fx-background-color: #ff9999;");GridPane.setColumnSpan(clearBtn, 2); // 跨2列grid.add(clearBtn, 0, 1);// 创建删除按钮Button deleteBtn = new Button("←");deleteBtn.setStyle("-fx-background-color: #ffff99;");GridPane.setColumnSpan(deleteBtn, 2); // 跨2列grid.add(deleteBtn, 2, 1);// 创建数字和运算符按钮for (int i = 0; i < 4; i++) {for (int j = 0; j < 4; j++) {Button btn = new Button(buttons[i][j]);btn.setStyle("-fx-font-size: 16px;");// 设置按钮大小btn.setPrefSize(60, 60);// 位置从第2行开始grid.add(btn, j, i + 2);// 为按钮添加点击事件btn.setOnAction(e -> {String text = btn.getText();if (text.equals("=")) {// 计算逻辑,这里简化处理try {// 使用JavaScript引擎计算表达式javax.script.ScriptEngine engine = new javax.script.ScriptEngineManager().getEngineByName("JavaScript");Object result = engine.eval(display.getText());display.setText(result.toString());} catch (Exception ex) {display.setText("错误");}} else {display.appendText(text);}});}}// 清除按钮事件clearBtn.setOnAction(e -> display.clear());// 删除按钮事件deleteBtn.setOnAction(e -> {String text = display.getText();if (!text.isEmpty()) {display.setText(text.substring(0, text.length() - 1));}});Scene scene = new Scene(grid, 280, 350);primaryStage.setTitle("简易计算器");primaryStage.setScene(scene);primaryStage.show();}public static void main(String[] args) {launch(args);}
}

        希望本章的内容能够帮助大家快速掌握 JavaFX 的基础知识。如果有任何疑问或建议,欢迎在评论区留言讨论!

http://www.lryc.cn/news/606523.html

相关文章:

  • MySQL 8.0 OCP 1Z0-908 题目解析(42)
  • 企业级部署 (基于tomcat与nginx)
  • Linux和shell
  • 【运维基础】Linux 文件系统基本管理
  • Side band ECC、Inline ECC、On-die ECC、Link ECC
  • chrome.storage 和 localStorage
  • Android 基础入门学习目录(持续更新)
  • kettle插件-kettle http client plus插件,轻松解决https接口无法调用文件流下载问题
  • 面试笔记【16:9区域问题】
  • SQL注入SQLi-LABS 靶场less25a-28a详细通关攻略
  • ESP32 外设驱动开发指南 (ESP-IDF框架)——GPIO篇:基础配置、外部中断与PWM(LEDC模块)应用
  • 机械学习--逻辑回归
  • 第1章:基础篇——第1节:基础操作与认识界面
  • Vercel 全面介绍与网站部署指南
  • 老旧远程控制管理模块(物联网设备)渗透实战:SNMP泄露+内核提权攻击链深度解析
  • Gold 序列
  • 7月31号打卡
  • nvm安装nodejs后提示No installations recognized
  • 爱普生002墨水与004墨水基本参数及支持机型
  • pyspark使用
  • 火焰图(Flame Graph)深度指南:CPU性能分析与瓶颈定位
  • STM32——HAL 库MDK工程创建
  • 计算机网络知识【推荐!!!】按照OSI七层模型梳理
  • 动手学习深度学习-深度学习知识大纲
  • Spring Boot + MinIO + KKFile:三步搭建企业级文件预览系统
  • SpringBoot3.x入门到精通系列:1.2 开发环境搭建
  • 前端核心技术Node.js(二)——path模块、HTTP与模块化
  • 2025年物联网新趋势:格行随身WiFi的模块化架构与低延迟优化
  • 代码随想录算法训练营第三十七天
  • 从C语言到C++:拥抱面向对象编程的全新世界