使用SceneBuilder创建用户界面
立即解锁
发布时间: 2025-08-19 02:09:18 阅读量: 3 订阅数: 5 


JavaFX 9:构建现代Java客户端应用的权威指南
### 使用Scene Builder创建用户界面
#### 1. FXML加载设施概述
在JavaFX中,FXML文件加载设施由`javafx.fxml`包中的两个类、一个接口、一个异常和一个注解组成。
- **FXMLLoader**:承担主要工作,如读取和解析FXML文件、识别处理指令、创建控制器对象并注入节点等。
- **JavaFXBuilderFactory**:负责根据FXMLLoader的请求创建各种对象的构建器。
- **Initializable接口**:在旧版本JavaFX中,控制器类可实现该接口接收FXMLLoader的信息,但此功能已被注入方法取代。
- **LoadException**:当FXML文件包含错误,导致FXMLLoader无法构建所有指定对象时抛出。
- **@FXML注解**:用于标记控制器类中的某些字段为注入目标,某些方法为事件处理候选。
#### 2. FXMLLoader类详解
##### 2.1 构造函数
FXMLLoader类有多个公共构造函数,参数少的构造函数会委托给参数多的构造函数,缺失的参数使用默认值。
| 构造函数 | 说明 |
| --- | --- |
| `FXMLLoader()` | 无参构造函数,使用默认值 |
| `FXMLLoader(URL location)` | 指定要加载的FXML文件的URL |
| `FXMLLoader(URL location, ResourceBundle resources)` | 指定URL和资源束 |
| `FXMLLoader(URL location, ResourceBundle resources, BuilderFactory builderFactory)` | 指定URL、资源束和构建器工厂 |
| `FXMLLoader(URL location, ResourceBundle resources, BuilderFactory builderFactory, Callback<Class<?>, Object> controllerFactory)` | 指定URL、资源束、构建器工厂和控制器工厂 |
| `FXMLLoader(Charset charset)` | 指定字符集 |
| `FXMLLoader(URL location, ResourceBundle resources, BuilderFactory builderFactory, Callback<Class<?>, Object> controllerFactory, Charset charset)` | 指定URL、资源束、构建器工厂、控制器工厂和字符集 |
| `FXMLLoader(URL location, ResourceBundle resources, BuilderFactory builderFactory, Callback<Class<?>, Object> controllerFactory, Charset charset, LinkedList<FXMLLoader> loaders)` | 指定所有参数 |
各参数说明:
- `location`:要加载的FXML文件的URL,默认值为`null`。
- `resources`:与FXML文件一起使用的资源束,用于国际化字符串,默认值为`null`。
- `builderFactory`:FXMLLoader用于获取各种对象构建器的工厂,默认是`JavaFXBuilderFactory`的实例。
- `controllerFactory`:一个`javafx.util.CallBack`,用于返回控制器实例,默认值为`null`。
- `charset`:解析FXML文件时使用的字符集,默认值为`UTF - 8`。
- `loaders`:FXMLLoader列表,默认值为一个空列表。
##### 2.2 获取和设置方法
FXMLLoader类有一系列获取和设置方法,用于改变其状态。
| 方法 | 说明 |
| --- | --- |
| `URL getLocation()` | 获取FXML文件的URL |
| `void setLocation(URL location)` | 设置FXML文件的URL |
| `ResourceBundle getResources()` | 获取资源束 |
| `void setResources(ResourceBundle resources)` | 设置资源束 |
| `ObservableMap<String, Object> getNamespace()` | 获取命名空间 |
| `<T> T getRoot()` | 获取根对象 |
| `void setRoot(Object root)` | 设置根对象 |
| `<T> T getController()` | 获取控制器 |
| `void setController(Object controller)` | 设置控制器 |
| `BuilderFactory getBuilderFactory()` | 获取构建器工厂 |
| `void setBuilderFactory(BuilderFactory builderFactory)` | 设置构建器工厂 |
| `Callback<Class<?>, Object> getControllerFactory()` | 获取控制器工厂 |
| `void setControllerFactory(Callback<Class<?>, Object> controllerFactory)` | 设置控制器工厂 |
| `Charset getCharset()` | 获取字符集 |
| `void setCharset(Charset charset)` | 设置字符集 |
| `ClassLoader getClassLoader()` | 获取类加载器 |
| `void setClassLoader(ClassLoader classLoader)` | 设置类加载器 |
##### 2.3 加载方法
FXMLLoader类有多个`load()`方法用于加载FXML文件。
```java
<T> T load() throws IOException
<T> T load(InputStream input) throws IOException
static <T> T load(URL location) throws IOException
static <T> T load(URL location, ResourceBundle resources) throws IOException
static <T> T load(URL location, ResourceBundle resources, BuilderFactory builderFactory) throws IOException
static <T> T load(URL location, ResourceBundle resources, BuilderFactory builderFactory, Callback<Class<?>, Object> controllerFactory) throws IOException
static <T> T load(URL location, ResourceBundle resources, BuilderFactory builderFactory, Callback<Class<?>, Object> controllerFactory, Charset charset) throws IOException
```
- 无参数的`load()`方法可在FXMLLoader实例的所有必要字段都已初始化后调用。
- 接受`InputStream`参数的`load()`方法将从指定输入加载FXML文件。
- 所有静态`load()`方法是便捷方法,会使用提供的参数实例化一个FXMLLoader,然后调用其非静态`load()`方法。
#### 3. 示例:FXMLLoaderExample
在这个示例中,我们故意不在FXML文件中指定`fx:controller`,并为控制器类添加了一个单参数构造函数。
**FXMLLoaderExample.fxml**
```xml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.web.WebView?>
<VBox maxHeight="-Infinity"
maxWidth="-Infinity"
minHeight="-Infinity"
minWidth="-Infinity"
prefHeight="400.0"
prefWidth="600.0"
spacing="10.0"
xmlns="http://javafx.com/javafx/8"
xmlns:fx="http://javafx.com/fxml/1">
<children>
<HBox spacing="10.0">
<children>
<TextField fx:id="address"
onAction="#actionHandler"
HBox.hgrow="ALWAYS">
<padding>
<Insets bottom="4.0" left="4.0" right="4.0" top="4.0"/>
</padding>
</TextField>
<Button fx:id="loadButton"
mnemonicParsing="false"
onAction="#actionHandler"
text="Load"/>
</children>
</HBox>
<WebView fx:id="webView"
prefHeight="200.0"
prefWidth="200.0"
VBox.vgrow="ALWAYS"/>
</children>
<padding>
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0"/>
</padding>
</VBox>
```
**FXMLLoaderExampleController.java**
```java
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
import javafx.scene.web.WebView;
public class FXMLLoaderExampleController {
@FXML
private TextField address;
@FXML
private WebView webView;
@FXML
private Button loadButton;
private String name;
public FXMLLoaderExampleController(String name) {
this.name = name;
}
@FXML
public void actionHandler() {
webView.getEngine().load(address.getText());
}
}
```
**FXMLLoaderExampleMain.java**
```java
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class FXMLLoaderExampleMain extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
FXMLLoader fxmlLoader = new FXMLLoader();
fxmlLoader.setLocation(
FXMLLoaderExampleMain.class.getResource("/FXMLLoaderExample.fxml"));
fxmlLoader.setController(
new FXMLLoaderExampleController("FXMLLoaderExampleController"));
final VBox vBox = fxmlLoader.load();
```
0
0
复制全文
相关推荐










