前面介绍了FXML的基本格式及其控制器的用法,算是打通了FXML方式的编码流程。程序界面通常保持固定尺寸,不过有时也允许用户拖曳窗口大小,不拖不打紧,一拖就可能坏事。像之前的登录窗口,没拖的时候界面如下图所示。


现在开始慢慢把窗口拖长,拖到一半停下来,此时登录界面如下图所示。


乍看过去,界面上的各控件大小保持不变,且始终居中显示,没发现什么问题。可是继续拖长窗口,突然之间这些控件乾坤大挪移,用户名区域顶到了第一行,登录按钮跟着顶到了第二行,变化后的界面效果如下图所示。


之所以出现控件排版错乱的问题,是因为该界面的根节点采用了流式窗格FlowPane。所谓流式,指的是从左到右排列,倘若没排满一行,就跟在当前行后面;只有排满了一行,才会另起一行继续排。刚刚拖拉窗口的时候,拖得太长了,导致窗口的宽度能够容纳登录类型与用户名两个区域,结果两块区域便挤到同一行了。显然这不是期望的界面布局,至少控件要老老实实呆在自己的位置,不可越雷池一步。
若想避免流式窗格排版飘忽的问题,可以使用垂直箱子VBox替换流式窗格,垂直箱子规定它的每个直接下级都占用一行,绝对不会产生两个直接下级挤在同一行的现象。于是修改原来的fxml文件,把根节点FlowPane换成VBox,对应的xml标签变为以下格式:

<VBox fx:controller="com.javafx.fxml.LoginController" xmlns:fx="http://javafx.com/fxml" alignment="center">
<!-- 这是xml注释标记。中间省略登录窗口的各控件标签 -->
</VBox>

fxml文件修改完毕,重新运行测试程序,弹出的登录窗口如下图所示。


现在不管怎样拉长窗口,各区域都留在当前行,再也不会乱跑了。然而采用VBox的界面很不协调,缘由在于VBox不支持hgap与vgap属性,因此各控件之间没能自动分隔开,几乎都粘在一起了,例如:
1、登录类型、用户名、密码三块区域的左侧直接顶到了窗口边缘;
2、用户名输入框、密码输入框、登录按钮三个自上往下紧紧贴着,不留一丝空隙;
似此过于紧凑的界面,令人感觉颇为拘谨,还是留个适当的间隔比较好。虽然VBox不支持hgap与vgap属性,但它另外提供了padding属性组,允许分别指定上、下、左、右四个方向的间距。padding节点挂在哪个VBox或HBox之下,就表示哪个箱子会在内部自动留白,padding对应的xml标签具体写法如下所示:

  <padding>
<Insets top="10.0" bottom="10.0" left="10.0" right="10.0"/>
</padding>

上述的padding节点例子,定义了在上、下、左、右四个方向各留出10个像素的空白间距。考虑到VBox和HBox下面可能挂着好几个子控件,为了更好地将这些子控件跟padding区分开,fxml又给VBox和HBox引入了children子节点,凡是下级控件统统放到children节点之下,而padding节点专门放置四个方向的间隔距离。如此一来,形态完整的VBox节点结构变成了以下这般:

<VBox fx:controller="com.javafx.fxml.LoginController" xmlns:fx="http://javafx.com/fxml" alignment="center">
<children>
<!-- 这是xml注释标记。中间省略VBox的下级控件列表 -->
</children>
<padding>
<Insets top="10.0" bottom="10.0" left="10.0" right="10.0"/>
</padding>
</VBox>

由上面的xml样例可以看到,改进之后的VBox标签变得层次分明、结构清晰,大大增强了它的可读性。
除此之外,fxml还为VBox和HBox提供了自动伸展功能,也就是说,随着窗口尺寸的增大,VBox和HBox的宽高也会随之增大。其中水平方向的宽度自适应,由属性HBox.hgrow控制,其值为ALWAYS时表示当前箱子的宽度跟随上级变化;垂直方向的宽度自适应则由属性VBox.vgrow控制,其值为ALWAYS时表示当前箱子的高度跟随上级变化。尤其需要注意的是,除了VBox和HBox这两个箱子支持自动伸展以外,只有几个输入框控件支持自动伸展,其中TextField与PasswordField只支持水平方向上的自动伸展,而TextArea同时支持水平与垂直两个方向的自动伸展。
利用fxml的几个新节点和新属性改造原先的登录界面,一方面,整个登录界面在窗口四周边缘均留白,各行之间也留出一条缝隙;另一方面,令用户名输入框和密码输入框支持水平伸展,令用户名区域和密码区域支持垂直伸展。这么改造一番之后的fxml文件示例如下:

<VBox fx:controller="com.javafx.fxml.LoginController" xmlns:fx="http://javafx.com/fxml" alignment="center">
<children>
<HBox fx:id="hbType" prefWidth="400" prefHeight="40">
<children>
<Label fx:id="labelType" prefWidth="120" prefHeight="40" text="登录类型:" />
<fx:define>
<ToggleGroup fx:id="tgType" />
</fx:define>
<RadioButton fx:id="rbPassword" prefWidth="140" prefHeight="40" toggleGroup="$tgType"
text="密码登录" selected="true" />
<RadioButton fx:id="rbVerifycode" prefWidth="140" prefHeight="40" toggleGroup="$tgType"
text="验证码登录" />
</children>
<padding>
<Insets top="0.0" bottom="10.0" left="0.0" right="0.0"/>
</padding>
</HBox>
<HBox fx:id="hbUser" prefWidth="400" prefHeight="40" VBox.vgrow="ALWAYS">
<children>
<Label fx:id="labelUser" prefWidth="120" prefHeight="40" text="用户名:" />
<TextField fx:id="fieldUser" prefWidth="280" prefHeight="40" HBox.hgrow="ALWAYS" />
</children>
<padding>
<Insets top="0.0" bottom="10.0" left="0.0" right="0.0"/>
</padding>
</HBox>
<HBox fx:id="hbPassword" prefWidth="400" prefHeight="40" VBox.vgrow="ALWAYS">
<children>
<Label fx:id="labelPassword" prefWidth="120" prefHeight="40" text="密 码:" />
<PasswordField fx:id="fieldPassword" prefWidth="280" prefHeight="40" HBox.hgrow="ALWAYS" />
</children>
<padding>
<Insets top="0.0" bottom="10.0" left="0.0" right="0.0"/>
</padding>
</HBox>
<Button fx:id="btnLogin" prefWidth="400" prefHeight="40" text="登  录" />
<Label fx:id="labelLoginResult" prefWidth="400" prefHeight="40" text="这里显示登录结果" />
</children>
<padding>
<Insets top="10.0" bottom="10.0" left="10.0" right="10.0"/>
</padding>
</VBox>

再次运行测试程序,弹出的登录窗口如下图所示,果然各级控件与周边都隔了一小段距离。


接着在水平方向拉长窗口,拉长之后的窗口界面如下面左图所示。回到初始尺寸,在垂直方向拉高窗口,拉高之后的如下面右图所示。


从上面两张效果图可见,几个箱子和输入框的宽高确实跟随窗口尺寸的变化而变化。


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

Java开发笔记(一百四十五)FXML布局的伸展适配的更多相关文章

  1. Java开发笔记(六十五)集合:HashSet和TreeSet

    对于相同类型的一组数据,虽然Java已经提供了数组加以表达,但是数组的结构实在太简单了,第一它无法直接添加新元素,第二它只能按照线性排列,故而数组用于基本的操作倒还凑合,若要用于复杂的处理就无法胜任了 ...

  2. Java开发笔记(八十五)通过字符流读写文件

    前面介绍了文件的信息获取.管理操作,以及目录下的文件遍历,那么文件内部数据又是怎样读写的呢?这正是本文所要阐述的内容.File工具固然强大,但它并不能直接读写文件,而要借助于其它工具方能开展读写操作. ...

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

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

  4. Java开发笔记(三十五)字符串格式化

    前面介绍了字符串变量的四种赋值方式,对于简单的赋值来说完全够用了,即便是两个字符串拼接,也只需通过加号把两个目标串连起来即可.但对于复杂的赋值来说就麻烦了,假设现在需要拼接一个很长的字符串,字符串内部 ...

  5. Java开发笔记(四十五)成员属性与成员方法

    前面介绍了许多数据类型,除了基本类型如整型int.双精度型double.布尔型boolean之外,还有高级一些的如包装整型Integer.字符串类型String.本地日期类型LocalDate等等,那 ...

  6. Java开发笔记(七十五)异常的处理:扔出与捕捉

    前面介绍的几种异常(不包含错误),编码的时候没认真看还发现不了,直到程序运行到特定的代码跑不下去了,程序员才会恍然大悟:原来这里的代码逻辑有问题.像这些在运行的时候才暴露出来的异常,又被称作“运行时异 ...

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

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

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

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

  9. Java开发笔记(三十二)字符型与整型相互转化

    前面提到字符类型是一种新的变量类型,然而编码实践的过程中却发现,某个具体的字符值居然可以赋值给整型变量!就像下面的例子代码那样,把字符值赋给整型变量,编译器不但没报错,而且还能正常运行! // 字符允 ...

随机推荐

  1. C# 构造基础返回值类型-BaseResponse

    学无止境,精益求精 十年河东,十年河西,莫欺少年穷 用于基础返回值类型,如下: using System; using System.Collections.Generic; using System ...

  2. javascript高级程序设计学习历程

    第三章 基本概念 3.1 语法 3.1.1 区分大小写 ECMAScript中的一切(变量,函数,操作符)都区分大小写的 3.1.2 标识符 标识符:变量,函数,属性的名字以及函数的参数. 标识符的命 ...

  3. Angular4项目运行时URL自动加#方法

    import {HashLocationStrategy , LocationStrategy} from '@angular/common'; @NgModule({   declarations: ...

  4. HTML 从入门到精通 [目录]

    目录 一.服务器的认识 二.浏览器的认识 三.Web 标准 四.HTML 的认识 五.HTML 文本标签 六.HTML 图像标签 七.HTML 路径 八.HTML 链接标签 九.HTML 列表 十.H ...

  5. es严格模式、对象和扩展。

    01. 严格模式 1. 理解: * 除了正常运行模式(混杂模式),ES5添加了第二种运行模式:"严格模式"(strict mode). * 顾名思义,这种模式使得Javascrip ...

  6. Bugku 多次

    网址:http://123.206.87.240:9004/1ndex.php?id=1 前言:bugku中一涉及多次注入的题 1.异或注入(判断字符是否被过滤) 0X00   很明显 注入点在id上 ...

  7. android studio学习----Android Studio导入github下载的工程--替换方法

    http://www.cnblogs.com/liuling/p/2015-9-16-01.html 这种方法是可行的,主要是先自己创建一个project ,然后把没有的文件夹都复制过去就OK了,特别 ...

  8. win中Oracle简易客户端和plsql的配置

    连接数据库有2种方式:在本机安装Oracle数据库或者是安装一个oracle简易客户端 当然,简易客户端跟oracle数据库比较少了一些功能 连接方式: 1)简易连接 sqlplus scott/ti ...

  9. Java枚举的用法和原理深入

    转载请注明原文地址:https://www.cnblogs.com/ygj0930/p/10843644.html 一:枚举的用法 1.定义和组织常量 在JDK1.5之前,我们定义常量都是:publi ...

  10. 源码解析 || ArrayList源码解析

    前言 这篇文章的ArrayList源码是基于jdk1.8版本的源码,如果与前后版本的实现细节出现不一致的地方请自己多加注意.先上一个它的结构图 ArrayList作为一个集合工具,对于我而言它值得我们 ...