前面介绍了如何通过fxml文件编排界面布局,可是光有静态界面根本没法处理业务,必须另外书写业务逻辑的代码,方能响应各按钮的单击事件,并将业务结果即使呈现到界面上。显然,fxml内部写不了Java代码,同时入口程序已经把控件都托管给了fxml文件,也无法在Application代码中干预控件的操作。既然整个界面都托付给了fxml,那么解铃还须系铃人,只能且必须由fxml指定后续的逻辑控制器。具体做法是在fxml的根节点中添加属性“fx:controller”,通过该属性设置当前界面的控制器路径。比如之前的登录布局文件login_with_flow.fxml,它的根节点是流式窗格FlowPane,所以就给FlowPane节点补充“fx:controller”的取值,详细的标签例子见下:

<FlowPane fx:controller="com.javafx.fxml.LoginController"
xmlns:fx="http://javafx.com/fxml" alignment="center" hgap="5" vgap="5">

由以上的FlowPane标签可知,它指定的控制器路径为“com.javafx.fxml.LoginController”,这个LoginController类正是login_with_flow.fxml对应的控制器代码。作为FXML专属的搭档,控制器也要符合一定的格式规范,首先它必须实现了接口Initializable,并重写该接口定义的initialize方法,这个方法顾名思义会在界面初始化之时调用。其次,控制器内部需要声明FXML文件定义好的控件编号,这样才能通过控件编号操作每个控件对象。下面便是一个控制器范本的代码示例:

//界面控制器必须实现自接口Initializable
public class LoginController implements Initializable {
@FXML
private 控件类型 控件编号; // 其中控件类型为JavaFX的控件类名,控件编号取自fxml文件中的fx:id @Override
public void initialize(URL location, ResourceBundle resources) { // 界面打开后的初始化操作
// 可在此给各控件设置单击事件或者选中事件,也可设置控件上的文本字体及其大小
}
}

仍以前述的登录窗口为例,它的布局文件名叫login_with_flow.fxml,同时fxml文件设定了界面对应的控制器叫做LoginController。注意到登录窗口拥有两个单选按钮和一个登录按钮,这三个按钮都应当触发单击或者选中事件,于是在控制器的代码中分别声明几个待操作的控件对象,对象名称与fxml中的fx:id保持一致。然后重写控制器的initialize方法,在该方法中各自调用三个按钮的setOnAction方法,用以注册单击或选中按钮后的触发事件。根据以上说明编写登录窗口的控制器代码示例如下:

//登录窗口的界面控制器
public class LoginController implements Initializable {
@FXML
private RadioButton rbPassword; // 密码登录对应的单选按钮
@FXML
private RadioButton rbVerifycode; // 验证码登录对应的单选按钮
@FXML
private Label labelUser; // 用户名标签
@FXML
private TextField fieldUser; // 用户名输入框
@FXML
private Label labelPassword; // 密码标签
@FXML
private PasswordField fieldPassword; // 密码输入框
@FXML
private Button btnLogin; // 登录按钮
@FXML
private Label labelLoginResult; // 登录结果标签 @Override
public void initialize(URL location, ResourceBundle resources) { // 界面打开后的初始化操作
rbPassword.setOnAction(e -> { // 选中“密码登录”单选按钮后触发的事件
labelUser.setText("用户名:");
labelPassword.setText("密 码:");
});
rbVerifycode.setOnAction(e -> { // 选中“验证码登录”单选按钮后触发的事件
labelUser.setText("手机号:");
labelPassword.setText("验证码:");
});
//
btnLogin.setOnAction(e -> { // 单击“登录”按钮后触发的事件
String result = String.format("您输入的用户名为%s,密码为%s",
fieldUser.getText(), fieldPassword.getText());
labelLoginResult.setText(result); // 在登录结果标签上显示登录信息
});
}
}

由上面代码可见,这个控制器的处理逻辑很简单,选中按钮后仅仅给文本标签设置指定文字而已,当然这样也方便观察控件的操作结果。

回到登录窗口的入口代码LoginMain,运行测试程序弹出如下图所示的登录界面。


由图示可见登录窗口默认选中“密码登录”,接着单击右边的“验证码登录”按钮,发现下方的用户名标签变成了“手机号:”,密码标签变成了“验证码:”,说明“验证码登录”按钮的选中事件被正常触发。然后分别在用户名输入框与密码输入框中填入用户名和密码,再单击下面的登录按钮,此时登录窗口的界面效果如下图所示。


果不其然,登录按钮下方的文本标签展示了输入的用户名和密码信息,可知登录按钮的单击事件也正确响应了。


更多Java技术文章参见《Java开发笔记(序)章节目录

Java开发笔记(一百四十四)实现FXML对应的控制器的更多相关文章

  1. Java开发笔记(三十四)字符串的赋值及类型转换

    不管是基本的char字符型,还是包装字符类型Character,它们的每个变量只能存放一个字符,无法满足对一串字符的加工.为了能够直接操作一连串的字符,Java设计了专门的字符串类型String,该类 ...

  2. Java开发笔记(八十四)文件与目录的管理

    程序除了处理内存中的数据结构,还要操作磁盘上的各类文件,这里的磁盘是个统称,泛指可以持久保留数据的存储介质,包括但不限于:插在软驱中的软盘.固定在机箱中的硬盘.插在光驱中的光盘.插在USB接口上的U盘 ...

  3. Java开发笔记(二十四)方法的组成形式

    经过前面的学习,我们发现演示的Java代码越来越复杂,而且每个例子的代码都堆在入口方法main内部,这会导致如下问题:1.一个方法内部堆砌了太多的代码行,看着费神,维护起来也吃力:2.部分代码描述的是 ...

  4. Java开发笔记(五十四)内部类和嵌套类

    通常情况下,一个Java代码文件只定义一个类,即使两个类是父类与子类的关系,也要把它们拆成两个代码文件分别定义.可是有些事物相互之间密切联系,又不同于父子类的继承关系,比如一棵树会开很多花朵,这些花儿 ...

  5. Java开发笔记(六十四)静态方法引用和实例方法引用

    前面介绍了方法引用的概念及其业务场景,虽然在所列举的案例之中方法引用确实好用,但是显而易见这些案例的适用场合非常狭窄,因为被引用的方法必须属于外层匿名方法(即Lambda表达式)的数据类型,像isEm ...

  6. Java开发笔记(七十四)内存溢出的两种错误

    前面介绍的几种异常,其实都存在这样那样的逻辑问题,属于程序员的编码手误.还有一大类系统错误,表面上看不出什么问题,但是程序仍然运行不下去,兹举二例说明.第一个例子且看下列的测试代码: // 测试内存溢 ...

  7. OpenCV开发笔记(六十四):红胖子8分钟带你深入了解SURF特征点(图文并茂+浅显易懂+程序源码)

    若该文为原创文章,未经允许不得转载原博主博客地址:https://blog.csdn.net/qq21497936原博主博客导航:https://blog.csdn.net/qq21497936/ar ...

  8. Java开发笔记(八十二)注解的基本单元——元注解

    Java的注解非但是一种标记,还是一种特殊的类型,并且拥有专门的类型定义.前面介绍的五种内置注解,都可以找到对应的类型定义代码,例如查看注解@Override的源码,发现它的代码定义是下面这样的: @ ...

  9. Java开发笔记(二十五)方法的输入参数

    前面通过main方法介绍了方法的定义形式,对于方法的输入参数来说,还有几个值得注意的地方,接下来分别对输入参数的几种用法进行阐述.一个方法可以有输入参数,也可以没有输入参数,倘若无需输入参数,则方法定 ...

  10. Java开发笔记(二十九)大整数BigInteger

    早期的编程语言为了节约计算机的内存,给数字变量定义了各种存储规格的数值类型,比如字节型byte只占用一个字节大小,短整型short占用两个字节大小,整型int占用四个字节大小,长整型long占用八个字 ...

随机推荐

  1. Game of Cards Gym - 101128G (SG函数)

    Problem G: Game of Cards \[ Time Limit: 1 s \quad Memory Limit: 256 MiB \] 题意 题意就是给出\(n\)堆扑克牌,然后给出一个 ...

  2. [ARC064F] Rotated Palindromes

    题意 给定一个整数N,请你求出有多少字符集为1到K之间整数的字符串,使得该字符串可以由一个长度为N的回文串循环移位后得到.所谓循环移位,就是把字符串的某个前缀(可以为空)移到字符串末尾,如" ...

  3. mknod

  4. Vuejs基本使用

    一.简单使用 ①首先需要实例化vue:new 出来,注意Vue大小写 ②通过el绑定元素:el 选项的作用就是告诉 Vue 管理模板的入口节点(不要绑定body和html) ③data:是响应式数据, ...

  5. Ubuntu下python3安装tkinter包

    case1: 首先sudo apt-get update(如果不更新很有可能找不到tkinter),然后sudo apt-get install python3-tk,安装完成后就可以使用了. cas ...

  6. 关于C++中extern的简单笔记

    extern可以实现多文件共享同一个变量.const常量.函数. 下面结合几个例子来讲一下extern的相关性质(下述皆为多文件编译): 例1: //file1.cpp #include<ios ...

  7. java项目里classpath具体指哪儿个路径

    一.classpath路径指什么 只知道把配置文件如:mybatis.xml.spring-web.xml.applicationContext.xml等放到src目录(就是存放代码.java文件的目 ...

  8. GEO Gene Expression Omnibus

    GEO  Gene Expression Omnibus 基因表达数据库 网址:https://www.ncbi.nlm.nih.gov/geo/ GEO的数据存储方式 GEO数据库具体存放四类数据: ...

  9. go - helloword

    package mainimport "fmt" //一定要双引号func main() {/* test hello word *///test fmt.Println(&quo ...

  10. java基础 小知识点汇总篇

    1.&和&& |和|| 的区别? a&b,会执行a,执行b ,得出结论 a&&b,会执行a,如果a false,则不执行b,直接返回false 2.Ma ...