博主纯业余,不是开发人员。 下面提到的四个文件: Main.java FxmlController.java FXML文件(.fxml) test.css

src{
	fx{
		Main.java
		FxmlController.java	}
	fxml{
		FXML文件(test.fxml)	}
	css{
		test.css } }
0.MVC框架

Model View Controller 经典MVC模式中,M是指业务模型,V是指用户界面,C则是控制器,使用MVC的目的是将M和V的实现代码分离,从而使同一个程序可以使用不同的表现形式。(-百度百科:MVC框架)

引用b站视频的评论 @东篱雪清 回复 @电脑玩家Rain :链接 8、HTML------------->FXML :结构 (美术人员) 9、CSS--------------->CSS: 外观权 (美术人员) 10、JavaScript-------->Controller.java : 行为 (开发人员)

1.选择器

JavaFX CSS文件里的选择器:(粗略的使用,未涉及深入的内容) 1.以#为前缀的ID选择器: #id{ …/* 按行写的带-fx前缀的css代码格式:属性:值 */ …} 根据ID选择设置过ID的组件。 例如:

#fxmlButton1{
    -fx-font-size: 18;
    -fx-background-color: black;
    -fx-text-fill:Snow;
}

2.以.为前缀的 类class 与 类型type 选择器: .className{ …/* 按行写的带-fx前缀的css代码格式 :属性:值*/ … } 同时改变一类组件。 例如:

.button{
    -fx-font-size: 18;
    -fx-background-color: black;
    -fx-text-fill:Snow;
}

3.给组件添加响应事件时的样式:(伪类选择器) selector : pseudo-class {…/* 按行写的带-fx前缀的css代码格式:属性:值 */ …} 例如:

/* 鼠标在按钮上悬停 对所有按钮都生效 */
.button:hover{
	-fx-background-color: blue;
}

注:css文件的语法错误等只有在调用到相关代码才能被报出来。

参考: 【JavaFX——CSS选择器 】

2.在FXML文件中指定控制器fx:controller

在FXML文件中在根结点添加指定控制器FxmlController.java语句: fx:controller=“包名.FxmlController” (只加载一次) 例如:

<AnchorPane fx:controller="fxControl.FxmlController" ... >

这样就能在FxmlController.java类中实现对组件的控制了。 但下面的标题6可以知道,也可以把事件响应写在Main.java里。

3.FxmlController.java

fxmlController.java中的@FXML注释标签: Main.java文件加载FXML文件,FXML文件实例化对象 例如:

public class FxmlController {

	@FXML
	private Button fxmlbutton;
	// 这个fxmlbutton已经被实例化了,
	// 实例化的对象就是FXML中以“fxmlbutton”为fx:id的组件。
	// fxmlbutton得到了FXML文件中<Button fx:id="fxmlbutton">的引用。
	
	public FxmlController(){
	}
	
	@FXML
	private void initialize(){
		System.out.println(fxmlbutton.getText()); //打印按钮上的文本
	}
}

正确的废话: 简单地说,@FXML标签和FXML文件内容对应。实际上对于public 即便不加此标签也能正确执行,但private 必须用到此标签。 而遵循规范的写法应该加上@FXML标签,以便在加载时得以执行。

4.加载FXML文件

在Main.java文件中的start方法或stop方法中添加加载FXML文件语句: 需使用FXMLLoader对象: FXMLLoader fxLoader = new FXMLLoader(); 例如:

FXMLLoader fxLoader = new FXMLLoader();
URL url = fxLoader.getClassLoader().getResource("fxml/test.fxml");//此处要用getClassLoader(),路径从src下开始,fx包名前不加"/"
fxLoader.setLocation(url);
AnchorPane root = (AnchorPane) fxLoader.load();

或等价写成:

AnchorPane root = FXMLLoader.load(getClass().getResource("test.fxml"));//此处用getClass()

load()方法原型:(至少有URL参数)

public static <T> T load(URL location,
                         ResourceBundle resources,
                         BuilderFactory builderFactory)
                  throws IOException
5.引入CSS文件

在Main.java文件中的start方法或stop方法中引入CSS文件语句: 使用Scene类对象加载: 例如:

Scene scene = new Scene(root);
URL url_css = this.getClass().getClassLoader().getResource("/CSS/test.css");
scene.getStylesheets().add(url_css.toExternalForm());

或等价写成:

Scene scene = new Scene(root);
scene.getStylesheets().add(getClass().getResource("/CSS/test.css").toExternalForm());
6.添加事件响应

比如给FXML里的<Button fx:id=“fxmlbutton”>添加一个事件 三种方法: 1.(推荐)在Main.java里通过控制器类FxmlController的实例化对象来实现控制: 需要在Main.java里实例化一个FxmlController类对象,比如叫做 fc,然后使用FxmlController类里自己写好的get方法(get方法不需要添加@FXML)返回组件。 关于多个监听器,如果通过方法3实例化对象后在Main.java里写动作,会取代(通过x:controller=“fxControl.FxmlController"与 onAction=”#buttonOnAction"组合的这种)方法2中FxmlController.java里写的动作。同一个文件出现重复的动作则后写的方法会覆盖先写的方法。 这种方式需要做的就是在FxmlController.java里写好组件的get方法,然后在Main.java里通过实例化FxmlController对象调用get方法获得组件的引用,然后写动作。 实例化FxmlController对象的方法:通过FXMLLoader类的实例化对象 .getController方法返回FxmlController实例。 例如: FxmlController.java文件:

@FXML
    public Button button1;

	//相应的get方法
	//button1的get方法,返回Button类
	public Button getButton1() {
        return button1;
    }

Main.java文件:

//加载fxml文件
    FXMLLoader fxLoader = new FXMLLoader();
    URL url = fxLoader.getClass().getResource("fileURL");
    fxLoader.setLocation(url);
    AnchorPane root = (AnchorPane) fxLoader.load();
    //把FxmlHandler类实例化:
    FxmlHandler fxmlHandler = fxLoader.getController();
    //获取组件的引用
    Button button1= fxmlHandler.getButton1();
    
    /* 然后在下面写响应的动作 */

	button1.setOnAction(new EventHandler<ActionEvent>() {
          @Override
          public void handle(ActionEvent event) {
              
          }
    });

之所以推荐这种写法,是因为这样易于处理组件与组件之间的相互调用。

2.在FXML文件的组件中直接以属性的方式指定,这样指定后就要在FXML中的fx:controller设定的文件中写事件响应: FXML文件中的代码:

<AnchorPane fx:controller="fxControl.FxmlController" ...>
	<Button onAction="#buttonOnAction" ...>
	...
</AnchorPane>

FxmlController.java中的代码:

@FXML
private void buttonOnAction(){
	...
}

3.可以通过在Main.java中用Button bu = root.lookup("#fxmlbutton"); 获得该组件,再在Main.java里写事件响应: FXML文件中的代码:

<AnchorPane ...>
	<Button fx:id="fxmlbutton" ...>
	...
</AnchorPane>

Main.java中的代码:

Button bu = root.lookup("#fxmlbutton");
7.关于带-fx前缀的CSS语句可以写在哪

1.单独的.css文件(写完后.需要把css文件引入java文件) 遵循CSS语法,自行搜索或参考JavaFX CSS官方文档。 2.可以直接写在Main.java文件里的javafx组件调用的setStyle()方法里,以引号包裹。 例如:

button.setStyle("-fx-background-color: black;" +
                "-fx-text-fill:Snow;");

3.写在FXML文件里的组件的<style></style>标签里。 例如:

<AnchorPane ...>
	<Button ...>
		<style>
			-fx-background-color: black;
			-fx-text-fill:Snow;
		</style>
		...
	</Button>
	...
</AnchorPane>

参考【JavaFX CSS官方文档:JavaFX CSS Reference Guide:】 https://docs.oracle.com/javafx/2/api/javafx/scene/doc-files/cssref.html 参考【Bilibili视频:JavaFX视频教程第119课,CSS的简单使用】 https://www.bilibili.com/video/BV1pb411s7cd

8.SceneBuilder可视化图形编辑工具

SceneBuilder可视化图形编辑工具: 下载地址:选择对应版本下载: (1)gluonhq.com下载: https://gluonhq.com/products/scene-builder/ (2)www.oracle.com下载: https://www.oracle.com/java/technologies/javafxscenebuilder-1x-archive-downloads.html 在开发工具导入: (1)Eclipse参考:【JavaFx教程】第一部分:Scene Builder (2)IDEA参考:IDEA中使用scene builder 使用: 在开发工具软件中右键点击.fxml文件,选择在SceneBuilder打开。

9.FXMLLoader加载文件路径的问题

上面说的文件都是在在同一个src文件夹下的某个包里,如果更改了图片资源文件夹、CSS、FXML文件位置,变成和src文件并列的情况,要修改地址,不然会报错。 而且,在FXML文件里的地址也要修改。 而且,即使IDEA上按住ctrl能点击跳转,也不意味着执行不出错。同样,不能跳转也不意味着是错的。 示例:(src、css、fxml位置并列) Main.java 的 start方法里: HostServices host = this.getHostServices(); String css = host.resolveURI(host.getDocumentBase(),“css/test1.css”); String fxml = host.resolveURI(host.getDocumentBase(),“fxml/test1.fxml”); FXMLLoader fxLoader = new FXMLLoader(); URL url_fxml = new URL(fxml); fxLoader.setLocation(url_fxml); AnchorPane root = fxLoader.load(); Scene scene = new Scene(root); scene.getStylesheets().add(css); primaryStage.show(); FXML文件某图片地址: <Image url="@…/res/img/test1.png" />

其他参考: 【JavaFX的API文档:(当前最新是15,修改路径中的数字15可以更换版本)】 https://openjfx.cn/javadoc/15/

【FXML + CSS 开发登陆界面】

【JavaFX入门(五):使用CSS样式美化你的UI控件】

【JavaFX中引用CSS文件出错的解决方法】

【JavaFX - 不多数不啰嗦,开始肯定要来个HelloWorld】

【JavaFX之FXController详解 】