需要使用JDK11, 推荐使用 https://adoptium.net/releases.html
JavaFX 11 不再是JDK的一部分, 需要单独安装, 或者直接通过Maven Dependency引入.
参考 https://stackoverflow.com/questions/52467561/intellij-cant-recognize-javafx-11-with-openjdk-11
Start Guide: https://openjfx.io/openjfx-docs/#introduction
如果不使用Maven, 需要在 https://gluonhq.com/products/javafx/ 下载对应版本的sdk,
https://www.oracle.com/corporate/features/understanding-java-9-modules.html
使用 Maven 创建 JavaFX 项目是较简单方便的一种方式, 不需要关心包依赖关系, 只需要手工初始化一个项目结构, 剩下的事都可以交给Maven处理.
项目结构如下, 其中resources目录下的资源文件, 可以放在 resources 根目录, 也可以放到resources/org/openjfx, 两者在App.java中的载入方式不同
├── javafx_test01 │ ├── pom.xml │ ├── src │ │ └── main │ │ ├── java │ │ │ ├── com │ │ │ │ └── rockbb │ │ │ │ ├── App.java │ │ │ │ ├── PrimaryController.java │ │ │ │ └── SecondaryController.java │ │ │ └── module-info.java │ │ └── resources │ │ └── com │ │ └── rockbb │ │ ├── primary.fxml │ │ ├── secondary.fxml │ │ └── styles.css └── settings.xml
指定JDK版本为11, javafx版本为17.0.1, javafx.maven.plugin使用最新的0.0.8
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.rockbb</groupId> <artifactId>javafx-test01</artifactId> <version>1.0-SNAPSHOT</version> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.release>11</maven.compiler.release> <javafx.version>17.0.1</javafx.version> <javafx.maven.plugin.version>0.0.8</javafx.maven.plugin.version> </properties> <dependencies> <dependency> <groupId>org.openjfx</groupId> <artifactId>javafx-controls</artifactId> <version>${javafx.version}</version> </dependency> <dependency> <groupId>org.openjfx</groupId> <artifactId>javafx-fxml</artifactId> <version>${javafx.version}</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version> <configuration> <release>${maven.compiler.release}</release> <source>${maven.compiler.release}</source> <target>${maven.compiler.release}</target> </configuration> </plugin> <plugin> <groupId>org.openjfx</groupId> <artifactId>javafx-maven-plugin</artifactId> <version>${javafx.maven.plugin.version}</version> <configuration> <jlinkImageName>hellofx</jlinkImageName> <launcher>launcher</launcher> <mainClass>hellofx/org.openjfx.App</mainClass> </configuration> </plugin> </plugins> </build> </project>
这里定义项目模块的可见度, 反射的可见度, 以及依赖的其他模块. 后面的opens ... to 和 exports 需要使用自己工程的包名
module hellofx { requires javafx.controls; requires javafx.fxml; opens com.rockbb to javafx.fxml; exports com.rockbb; }
这是应用的入口. 下面的载入方式对应资源文件在根目录, 如果要按 package 放, 去掉其中的.getClassLoader()
就可以了
package com.rockbb; import javafx.application.Application; import javafx.fxml.FXMLLoader; import javafx.scene.Parent; import javafx.scene.Scene; import javafx.stage.Stage; import java.io.IOException; public class App extends Application { private static Scene scene; @Override public void start(Stage stage) throws IOException { scene = new Scene(loadFXML("primary")); scene.getStylesheets().add(getClass().getResource("styles.css").toExternalForm()); stage.setScene(scene); stage.show(); } static void setRoot(String fxml) throws IOException { scene.setRoot(loadFXML(fxml)); } private static Parent loadFXML(String fxml) throws IOException { FXMLLoader fxmlLoader = new FXMLLoader(App.class.getResource(fxml + ".fxml")); return fxmlLoader.load(); } public static void main(String[] args) { launch(); } }
package com.rockbb; import java.io.IOException; import javafx.fxml.FXML; import javafx.scene.control.Button; public class PrimaryController { public Button primaryButton; @FXML private void switchToSecondary() throws IOException { App.setRoot("secondary"); } }
package com.rockbb; import java.io.IOException; import javafx.fxml.FXML; import javafx.scene.control.Button; public class SecondaryController { public Button secondaryButton; @FXML private void switchToPrimary() throws IOException { App.setRoot("primary"); } }
<?xml version="1.0" encoding="UTF-8"?> <?import javafx.scene.layout.VBox?> <?import javafx.scene.control.Label?> <?import javafx.scene.control.Button?> <?import javafx.geometry.Insets?> <VBox alignment="CENTER" spacing="20.0" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.rockbb.PrimaryController"> <padding> <Insets bottom="20.0" left="20.0" right="20.0" top="20.0"/> </padding> <Label text="Primary View"/> <Button fx:id="primaryButton" text="Switch to Secondary View" onAction="#switchToSecondary"/> </VBox>
<?xml version="1.0" encoding="UTF-8"?> <?import javafx.scene.layout.VBox?> <?import javafx.scene.control.Label?> <?import javafx.scene.control.Button?> <?import javafx.geometry.Insets?> <VBox alignment="CENTER" spacing="20.0" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.rockbb.SecondaryController"> <padding> <Insets bottom="20.0" left="20.0" right="20.0" top="20.0"/> </padding> <Label text="Secondary View"/> <Button fx:id="secondaryButton" text="Switch to Primary View" onAction="#switchToPrimary"/> </VBox>
.button { -fx-text-fill: blue; }
IDEA中在App类上右键菜单, 点Run即可运行