javafx之FXML初探

FXML作为XML-based,UI构造器。其相关的规则值得我们去理解。

FXML元素分类:

  • A class instance
  • A property of a class instance
  • A "static" property
  • A "define" block
  • A block of script code

FXML应该在根元素定义prefix : xmlns:fx=http://javafx.com/xml

Class instance 元素

实例声明

<?import javafx.scene.control.Label?>
<Label text="Hello, World!"/>

Maps

<HashMap foo="123" bar="456"/>

fx:value-对于没有默认构造器的类如String,Double等但是有valueOf方法的

<String fx:value="Hello, World!"/>
<Double fx:value="1.0"/>
<Boolean fx:value="false"/>

fx:factory-对于使用静态工厂方法的

<FXCollections fx:factory="observableArrayList">
    <String fx:value="A"/>
    <String fx:value="B"/>
    <String fx:value="C"/>
</FXCollections>

Builders使用构造器模式的类:如Color

<Color red="1.0" green="0.0" blue="0.0"/>
<Color>
    <red>1.0</red>
    <green>0.0</green>
    <blue>0.0</blue>
</Color>

fx:include-包含另一个fxml文件或者国际化资源文件resource bundle

<fx:include source="filename"/>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<VBox xmlns:fx="http://javafx.com/fxml">
    <children>
        <fx:include source="my_button.fxml"/>
    </children>
</VBox>

my_button.fxml

<?import javafx.scene.control.*?>
<Button text="My Button"/>

包含国际化资源文件

<fx:include source="filename" resources="resource_file" charset="utf-8"/>

fx:constant

<Button>
    <minHeight><Double fx:constant="NEGATIVE_INFINITY"/></minHeight>
</Button>

fx:reference-通过fx:id进行引用

<ImageView>
    <image>
        <fx:reference source="myImage"/> //用于替代ImageView的image属性
    </image>
</ImageView>
<ArrayList>
    <fx:reference source="element1"/>
    <fx:reference source="element2"/>
    <fx:reference source="element3"/>
</ArrayList>

fx:copy-暂时别用,以后也许会改变

fx:root-指向root元素

Property元素

property元素支持强制类型转换。

分为:

  • A property setter
  • A read-only list property
  • A read-only map property

Property Setters

<?import javafx.scene.control.Label?>
<Label>
    <text>Hello, World!</text>
</Label>
<?import javafx.scene.control.Label?>
<Label text="Hello, World!"/>

ReadOnly List Property

<Group xmlns:fx="http://javafx.com/fxml">
    <children>
        <Rectangle fx:id="rectangle" x="10" y="10" width="320" height="240"
            fill="#ff0000"/>
        ...
    </children>
</Group>

ReadOnly Map Property

<?import javafx.scene.control.*?>
<Button>
    <properties foo="123" bar="456"/>
</Button>

Default Property

<?import javafx.scene.*?>
<?import javafx.scene.shape.*?>
<VBox xmlns:fx="http://javafx.com/fxml">
    <Button text="Click Me!"/>
    ...
</VBox>

Static Property

<GridPane>
    <children>
        <Label text="My Label">
            <GridPane.rowIndex>0</GridPane.rowIndex>
       <GridPane.columnIndex>0</GridPane.columnIndex>
        </Label>
    </children>
</TabPane>

定义Blocks----fx:define

fx:define定义的内容不会被添加到Scene Graph,最典型的应用就是单选按钮组中ToggleGroup的fx:define

引用它之前需要添加符号$

<VBox>
    <fx:define>
        <ToggleGroup fx:id="myToggleGroup"/>
    </fx:define>
    <children>
        <RadioButton text="A" toggleGroup="$myToggleGroup"/>
        <RadioButton text="B" toggleGroup="$myToggleGroup"/>
        <RadioButton text="C" toggleGroup="$myToggleGroup"/>
    </children>
</VBox>

Attributes:

分类:

  • A property of a class instance
  • A "static" property
  • An event handler

Property Attribute与Property Element是有区别:

1.property attribute只有当元素关闭时才会生效

2.property attribute还支持解析操作(resolution operators):

  • Location resolution位置解析
  • Resource resolution国际化资源解析
  • Variable resolution变量解析

Location resolution

@代表与当前fxml文件在同一目录

<ImageView>
    <image>
        <Image url="@my_image.png"/>
    </image>
</ImageView>

注意@路径解析后面接的必须是已经被URL编码的字符。如My Image.jpg应该写成这样

<Image url="@My%20Image.png"/>

Resource resolution

%代表该字符变量应该用国际化资源解析

<Label text="%myText"/>

Variable resolution

$代表需要进行变量解析,一般与fx:define配合使用

<fx:define>
    <ToggleGroup fx:id="myToggleGroup"/>
</fx:define>
...
<RadioButton text="A" toggleGroup="$myToggleGroup"/>
<RadioButton text="B" toggleGroup="$myToggleGroup"/>

转义处理:

<Label text="\$10.00"/>

表达式绑定:

${expr}

<TextField fx:id="textField"/>
<Label text="${textField.text}"/>

支持的其他操作:

"string"

‘string‘

A string constant
true

false

A boolean constant
null A constant representing the null value
50.0

3e5

42

A numerical constant
-

(unary operator)

Unary minus operator, applied on a number
!

(unary operator)

Unary negation of a boolean
+ -

* / %

Numerical binary operators
&& || Boolean binary operators
> >=

< <=

== !=

Binary operators of comparison.

Both arguments must be of type Comparable

Static Properties与Instance Properties类似

static properties attribute与element有点区别:

  <Label text="My Label" GridPane.rowIndex="0" GridPane.columnIndex="0"/>

EventHandlers

适用于setOnEvent类的方法(如setOnAction)

脚本化处理方式:

使用javascript声明与脚本

<?language javascript?>
...

<VBox>
    <children>
        <Button text="Click Me!"
            onAction="java.lang.System.out.println(‘You clicked me!‘);"/>
    </children>
</VBox>

控制器类Controller方法处理方式:

注意#号,与@FXML注解

<VBox fx:controller="com.foo.MyController"
    xmlns:fx="http://javafx.com/fxml">
    <children>
        <Button text="Click Me!" onAction="#handleButtonAction"/>
    </children>
</VBox>
public class MyController {
   @FXML public void handleButtonAction(ActionEvent event) {
        System.out.println("You clicked me!");
    }
}

下面这种方式也是有效的

public class MyController {
    public void handleButtonAction() {
        System.out.println("You clicked me!");
    }
}

对于Collections与properties的特殊的处理

ObservableList, ObservableMap orObservableSet uses
a special onChange attribute that points
to a handler method with aListChangeListner.Change, MapChangeListener.Change or SetChangeListener.Changeparameter
respectively.

<VBox fx:controller="com.foo.MyController"
    xmlns:fx="http://javafx.com/fxml">
    <children onChange="#handleChildrenChange"/>
</VBox>
public class MyController {
    public void handleChildrenChange(ListChangeListener.Change c) {
        System.out.println("Children changed!");
    }
}

对于parent property的处理:

public class MyController {
    public void handleParentChange(ObservableValue value, Parent oldValue, Parent newValue) {
        System.out.println("Parent changed!");
    }
}
<VBox fx:controller="com.foo.MyController"
    xmlns:fx="http://javafx.com/fxml" onParentChange="#handleParentChange"/>

Scripting脚本化

<?language javascript?>

<fx:script>

<?language javascript?>

<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>

<VBox xmlns:fx="http://javafx.com/fxml">
    <fx:script>

    function handleButtonAction(event) {
       java.lang.System.out.println(‘You clicked me!‘);
    }
    </fx:script>

    <children>
        <Button text="Click Me!" onAction="handleButtonAction(event);"/>
    </children>
</VBox>

从外部文件读取脚本。

<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>

<VBox xmlns:fx="http://javafx.com/fxml">
    <fx:script source="example.js" charset="cp1252"/>

    <children>
        <Button text="Click Me!" onAction="handleButtonAction(event);"/>
    </children>
</VBox>

example.js:

function handleButtonAction(event) {
   java.lang.System.out.println(‘You clicked me!‘);
}
<fx:script>
var myText = "This is the text of my label.";
</fx:script>

...

<Label text="$myText"/>

Controllers

fx:controller

<VBox fx:controller="com.foo.MyController"
    xmlns:fx="http://javafx.com/fxml">
    <children>
        <Button text="Click Me!" onAction="#handleButtonAction"/>
    </children>
</VBox>
public class MyController {
    public void handleButtonAction(ActionEvent event) {
        System.out.println("You clicked me!");
    }
}

当然Controllers类还可以实现Initializable接口,以便在被加载时可以调用初始化方法initialize()

<VBox fx:controller="com.foo.MyController"
    xmlns:fx="http://javafx.com/fxml">
    <children>
        <Button fx:id="button" text="Click Me!"/>
    </children>
</VBox>
package com.foo;

public class MyController implements Initializable {
    public Button button;

    @Override
    public void initialize(URL location, Resources resources)
        button.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                System.out.println("You clicked me!");
            }

前面介绍的都是通过public修饰field与方法,但是这破坏了封装性原则。

由于controller是对FXML Loader可见的,所以没必要对外部开放访问权限。

这样我们就必须通过@FXML注解进行修饰。

public class MyController {
    @FXML
    private void handleButtonAction(ActionEvent event) {
        System.out.println("You clicked me!");
    }
}
public class MyController implements Initializable {
    @FXML private Button button;

    @FXML
    protected void initialize()
        button.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                System.out.println("You clicked me!");
            }

Nested Controllers嵌套的控制器访问。

FXMLLoader

URL location = getClass().getResource("example.fxml");
ResourceBundle resources = ResourceBundle.getBundle("com.foo.example");
FXMLLoader fxmlLoader = new FXMLLoader(location, resources);

Pane root = (Pane)fxmlLoader.load();
MyController controller = (MyController)fxmlLoader.getController();

使用FXML结合FXMLLoader自定义UI组件

通过使用<fx:root>元素指定root元素的类型:

<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>

<fx:root type="javafx.scene.layout.VBox" xmlns:fx="http://javafx.com/fxml">
    <TextField fx:id="textField"/>
    <Button text="Click Me" onAction="#doSomething"/>
</fx:root>

自定义的UI组件:

package fxml;

import java.io.IOException;

import javafx.beans.property.StringProperty;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.control.TextField;
import javafx.scene.layout.VBox;

public class CustomControl extends VBox {
    @FXML private TextField textField;

    public CustomControl() {
        FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("custom_control.fxml"));
        fxmlLoader.setRoot(this);
        fxmlLoader.setController(this);

        try {
            fxmlLoader.load();
        } catch (IOException exception) {
            throw new RuntimeException(exception);
        }
    }

    public String getText() {
        return textProperty().get();
    }

    public void setText(String value) {
        textProperty().set(value);
    }

    public StringProperty textProperty() {
        return textField.textProperty();
    }

    @FXML
    protected void doSomething() {
        System.out.println("The button was clicked!");
    }
}

使用自定义的UI组件:

HBox hbox = new HBox();
CustomControl customControl = new CustomControl();
customControl.setText("Hello World!");
hbox.getChildren().add(customControl);

<HBox>
    <CustomControl text="Hello World!"/>
</HBox>

时间: 2024-10-18 08:04:05

javafx之FXML初探的相关文章

javafx之CSS初探

javaFX 可以通过css来设计界面.javafx中的css只是w3c css2.1规范的一个扩展和子集,并不完全支持所有的css特性. javafx中的css元素必须有-fx-前缀. 一.介绍 java8中新增了javafx.css开放了css相关api. 选择器分类: Type选择器:通过Node的getTypeSelector可以获取 id选择器:通过设定id=属性(注意这里的id不是fx:id) styleClass属性: styleClass可以使用class选择器 选择器命名规范:

JavaFX 初学入门(一):FXML嵌套与原始控件继承

说明 之前由于做一个小项目需要用swing,结果swing把我折腾的够呛.后来得知有javaFX这个类似于C#中WPF形式的利用XML来写界面的框架之后,马上就转到javaFX上了.找过一些资料但是帮助都不大,最后还是选择直接看官方demo.(我之前是做过android app,有些东西其实都是差不多的.) 下面选取官方demo中的一个 UnlockCustom . 这个demo中涉及到 继承原始控件(自定义),FXML 布局嵌套,以及一些控件动画等. 一.javaFX的入口函数 整个javaF

JavaFX学习之道:FXML入门

FXML是JavaFX 2.0提供的新技术.你可能会问"什么是FXML?","对我来说有什么用?". FXML是一种在JavaFX应用程序中定义用户界面的,基于XML的声明性标记语言.FXML非常适合用来静态布局,如表单.控件和表格.使用FXML,您还可以通过脚本动态地构建布局. FXML的优势之一是基于XML,是大多数开发人员所熟悉的,尤其是Web开发人员和使用其他RIA平台的开发人员.另一个优点是,FXML是不是编译语言,你不需要重新编译代码就可看到您所做的更改

IntelliJ IDEA创建JavaFX项目

点击File>New>Project,选中Java FX,Next,填写项目名称和路径,Finish 项目创建成功,目录如下,src下为项目源码,out目录下为编译结果. Main为项目主入口,sample.fxml为资源文件,可以看到main方法选择从sample.fxml加载窗口元素. Main.java和sample.fxml初始代码 public class Main extends Application { @Override public void start(Stage pri

JavaFX基础学习之URLConnection

一个标准的JavaFX文件包含三个部分:主类 . 控制类. 界面设计(XML+CSS) 1,main.java package application; import javafx.application.Application; import javafx.fxml.FXMLLoader; import javafx.stage.Stage; import javafx.scene.Parent; import javafx.scene.Scene; public class Main ext

JavaFX 二 First Blood(第一个小例子,拿起武器冲啊~)

万万没想到,上次写的JavaFX 一,回应那么激烈,令我有点小激动啊,这里感谢各位这么热心,大家的支持就是我最大的动力,让我们共同进步,共同学习.话题回归,今天我想给大家讲讲JavaFX的第一个小例子,顺便通过例子,给大家讲讲一些关于JavaFX的代码编写的一些心得体会.不多废话,好戏即将开始...... 上次说到新手开发是先Fxml,再写代码,我们先来看看如何用JavaFX Scene Builder 2.0设计我们想要的界面,首先,我介绍下工具界面的一些小知识, 首先我们认识下这个FX的可视

JavaFX学习之TableView

package application; import java.net.URL; import java.util.ResourceBundle; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.fxml.FXML; import javafx.fxml.Initializable; import javafx.scene.control.Table

javafx

源码 DialogAPP.zip 环境netbean   org.postgresql.Driver version 9 1 /* 2 * To change this license header, choose License Headers in Project Properties. 3 * To change this template file, choose Tools | Templates 4 * and open the template in the editor. 5 *

JavaFX之FXController详解

在JavaFX的UI开发中,FXController是个很重要的东西,主要是用于UI层和事件层分离. 事实上,JavaFX使用FXML来开发UI界面,有多种形式来监听我们的事件,下面我们来细看. 1.通过Controller Class来处理事件 首先我们创建一个简单的界面,包含一个Button和一个Label. 如下图: Label的fx:id设置为mLabel,Button的fx:id设置为mButton,同时将Button的onAction设置为onButtonClick. 如下图所示: