javafx之FXML初探
时间:2014-04-30 22:16:38
收藏:0
阅读:655
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"/>
<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
<?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>
评论(0)