Spec-Zone .ru
спецификации, руководства, описания, API
|
Последнее обновление: 21.06.2012
FXML является scriptable, основанным на XML языком разметки для того, чтобы создать графы объектов Java. Это обеспечивает удобную альтернативу построению таких графиков в процедурном коде, и идеально подходит для определения пользовательского интерфейса приложения JavaFX, так как иерархическая структура XML-документа близко параллельна структуре графика сцены JavaFX.
Этот документ представляет язык разметки FXML и объясняет, как это может использоваться, чтобы упростить разработку приложений JavaFX.
В FXML элемент XML представляет одно из следующего:
Экземпляры класса, свойства экземпляра, статические свойства, и определяют блоки, обсуждаются в этом разделе ниже. Сценарии обсуждаются в более позднем разделе.
Экземпляры класса могут быть созданы в FXML несколькими способами. Наиболее распространенное через элементы объявления экземпляра, которые просто создают новый экземпляр class по имени. Другие способы создать экземпляры class включают ссылающиеся существующие значения, копируя существующие значения, и включая внешние файлы FXML. Каждый обсуждается более подробно ниже.
<?import javafx.scene.control.Label?>
Этот PI импортирует все классы из javafx.scene.control пакета в текущее пространство имен:
<?import javafx.scene.control.*?>
<?import javafx.scene.control.Label?> <Label text="Hello, World!"/>
Отметьте, что "текстовое" свойство Метки в этом примере устанавливается, используя атрибут XML. Свойства могут также быть установлены, используя вложенные элементы свойства. Элементы свойства обсуждаются более подробно позже в этом разделе. Атрибуты свойства обсуждаются в более позднем разделе.
Классы, которые не соответствуют Бобовым соглашениям, могут также быть созданы в FXML, используя объект, названный "разработчиком". Разработчики обсуждаются более подробно позже.
Внутренне, загрузчик FXML использует экземпляр com.sun.javafx.fxml. BeanAdapter, чтобы обернуть инстанцированный объект и вызвать его методы метода set. Этот (в настоящий момент) частный class реализует java.util. Интерфейс карты и позволяет вызывающей стороне получать и устанавливать Бобовые значения свойств как пары ключ/значение.
<HashMap foo="123" bar="456"/>
<String fx:value="Hello, World!"/> <Double fx:value="1.0"/> <Boolean fx:value="false"/>
Пользовательские классы, которые определяют статический valueOf (Строка) метод, могут также быть созданы этот путь.
<FXCollections fx:factory="observableArrayList"> <String fx:value="A"/> <String fx:value="B"/> <String fx:value="C"/> </FXCollections>
Поддержка разработчика в FXML оказывается двумя интерфейсами. javafx.util. Интерфейс разработчика определяет единственный названный метод, создают (), который ответственен за построение фактического объекта:
public interface Builder<T> { public T build(); }
javafx.util. BuilderFactory ответственен за создание разработчиков, которые способны к инстанцированию данного типа:
public interface BuilderFactory { public Builder<?> getBuilder(Class<?> type); }
Разработчику значения по умолчанию фабрика, JavaFXBuilderFactory, предоставляют в javafx.fxml пакете. Эта фабрика способна к созданию и конфигурированию большинства неизменных типов JavaFX. Например, следующая разметка использует разработчика значения по умолчанию, чтобы создать экземпляр неизменного javafx.scene.paint. Цветной class:
<Color red="1.0" green="0.0" blue="0.0"/>
Отметьте, что, в отличие от Бобовых типов, которые создаются, когда тег запуска элемента обрабатывается, объекты, созданные разработчиком, не инстанцируют, пока закрывающий тэг элемента не достигается. Это - то, потому что все необходимые параметры, возможно, не доступны, пока элемент не был полностью обработан. Например, Цветной объект в предыдущем примере мог также быть записан как:
<Color> <red>1.0</red> <green>0.0</green> <blue>0.0</blue> </Color>
Цветной экземпляр не может быть полностью создан, пока все три из компонентов цвета не известны.
Обрабатывая разметку для объекта, который будет создан разработчиком, экземпляры Разработчика обрабатываются как объекты значения - если Разработчик реализует интерфейс Карты, помещенный (), метод используется, чтобы установить значения атрибута разработчика. Иначе, разработчик обертывается в BeanAdapter, и его свойства, как предполагается, представляются через стандартные Бобовые методы set.
<fx:include> тег создает объект из разметки FXML, определенной в другом файле. Это используется следующим образом:
<fx:include source="filename"/>
где имя файла является именем файла FXML, чтобы включать.
Например, учитывая следующую разметку:
<?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"/>
получающийся график сцены содержал бы VBox как корневой объект с единственной Кнопкой как дочерний узел.
Отметьте использование "fx" префикса пространства имен. Это - зарезервированный префикс, который определяет много элементов и атрибутов, которые используются для внутренней обработки исходного файла FXML. Это обычно объявляется на корневом элементе документа FXML. Другие функции, обеспеченные "fx" пространством имен, описываются в следующих разделах.
<fx:include> также поддерживает атрибуты для того, чтобы определить имя пакета ресурса, который должен использоваться, чтобы локализовать включенный контент, так же как набор символов, используемый, чтобы закодировать исходный файл. Разрешение ресурса обсуждается в более позднем разделе.
<Button> <minHeight><Double fx:constant="NEGATIVE_INFINITY"/></minHeight> </Button>
Например, следующая разметка присваивает ранее определенный экземпляр Изображения, названный "myImage" к свойству "изображения" управления ImageView:
<ImageView> <image> <fx:reference source="myImage"/> </image> </ImageView>
Отметьте, что, так как также возможно разыменовать переменную, используя оператор разрешения переменной атрибута (обсужденный позже в разделе Атрибутов), fx:reference обычно только используется, когда ссылочное значение должно быть определено как элемент, такой, добавляя ссылку на набор:
<ArrayList> <fx:reference source="element1"/> <fx:reference source="element2"/> <fx:reference source="element3"/> </ArrayList>
Для большинства других случаев, используя атрибут более просто и более краток.
В настоящее время никакие классы платформы JavaFX не предоставляют такому конструктору копии, таким образом, этот элемент обеспечивается прежде всего для использования разработчиками приложений. Это может измениться в будущем выпуске.
Элементы, имена тега которых начинаются со строчной буквы, представляют объектные свойства. Элемент свойства может представить одно из следующего:
Например, следующий FXML создает экземпляр Метки class и устанавливает значение "текстового" свойства метки к "Привет, Мир!":
<?import javafx.scene.control.Label?> <Label> <text>Hello, World!</text> </Label>
Это приводит к тому же самому результату как более ранний пример, который использовал атрибут, чтобы установить "текстовое" свойство:
<?import javafx.scene.control.Label?> <Label text="Hello, World!"/>
Элементы свойства обычно используются, когда значение свойства является составным типом, который не может быть представлен, используя простое основанное на операция со строками значение атрибута, или когда символьная длина значения является такой длинной, что, определяя у этого как атрибут было бы негативное воздействие на удобочитаемости.
Загрузчик FXML использует принуждение () метод BeanAdapter, чтобы выполнить любые необходимые преобразования типов. Этот метод способен к выполнению основных преобразований типа примитива, таких как Строка к булеву или международному, чтобы удвоиться, и также преобразует Строку в Класс или Строку к Перечислению. Дополнительные преобразования могут быть реализованы, определяя статический valueOf () метод на целевом типе.
Например, "дочернее" свойство javafx.scene. Группа является свойством списка только для чтения, представляющим дочерние узлы группы:
<?import javafx.scene.*?> <?import javafx.scene.shape.*?> <Group xmlns:fx="http://javafx.com/fxml"> <children> <Rectangle fx:id="rectangle" x="10" y="10" width="320" height="240" fill="#ff0000"/> ... </children> </Group>
Как каждый подэлемент <дочерние элементы> читается элемент, это добавляется к списку, возвращенному Group#getChildren ().
Свойство "свойств" javafx.scene. Узел является примером свойства карты только для чтения. Следующая разметка устанавливает свойства "foo" и "панели" экземпляра Метки к "123" и "456", соответственно:
<?import javafx.scene.control.*?> <Button> <properties foo="123" bar="456"/> </Button>
Например, с тех пор javafx.scene.layout. Область (суперкласс javafx.scene.layout. VBox), определяет свойство значения по умолчанию "дочерних элементов", <дочерние элементы>, элемент не требуется; загрузчик автоматически добавит подэлементы VBox к "дочернему" набору контейнера:
<?import javafx.scene.*?> <?import javafx.scene.shape.*?> <VBox xmlns:fx="http://javafx.com/fxml"> <Button text="Click Me!"/> ... </VBox>
Отметьте, что свойства значения по умолчанию не ограничиваются наборами. Если свойство значения по умолчанию элемента обратится к скалярному значению, то любой подэлемент того элемента будет установлен как значение свойства.
Например, с тех пор javafx.scene.control. ScrollPane определяет свойство значения по умолчанию "контента", область прокрутки, содержащая TextArea, поскольку его контент может быть определен следующим образом:
<ScrollPane> <TextArea text="Once upon a time..."/> </ScrollPane>
Использование в своих интересах свойств значения по умолчанию может значительно уменьшить многословие разметки FXML.
Статические свойства снабжаются префиксом имя class, который определяет их. Например, следующий FXML вызывает статический метод set для "rowIndex" GridPane и "columnIndex" свойств:
<GridPane> <children> <Label text="My Label"> <GridPane.rowIndex>0</GridPane.rowIndex> <GridPane.columnIndex>0</GridPane.columnIndex> </Label> </children> </TabPane>
Это преобразовывает примерно в следующее в Java:
GridPane gridPane = new GridPane(); Label label = new Label(); label.setText("My Label"); GridPane.setRowIndex(label, 0); GridPane.setColumnIndex(label, 0); gridPane.getChildren().add(label);Звонки GridPane#setRowIndex () и GridPane#setColumnIndex () "присоединяют" индексировать данные к экземпляру Метки. GridPane тогда использует их во время расположения, чтобы расположить его дочерние элементы соответственно. Другие контейнеры, включая AnchorPane, BorderPane, и StackPane, определяют подобные свойства.
Как со свойствами экземпляра, обычно используются статические элементы свойства, когда значение свойства не может быть эффективно представлено значением атрибута. Иначе, статические атрибуты свойства (обсужденный в более позднем разделе) обычно произведут более краткую и читаемую разметку.
Например, работая с переключателями, распространено определить ToggleGroup, который будет управлять состоянием выбора кнопок. Эта группа не является частью графика сцены непосредственно, так не должен быть добавлен к родителю кнопок. Определить блок может использоваться, чтобы создать группу кнопки, не вмешиваясь в полную структуру документа:
<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>
Элементы в определяют блоки, обычно присваиваются ID, который может использоваться, чтобы обратиться к значению элемента позже. ID обсуждаются более подробно в более поздних разделах.
Атрибут в FXML может представить одно из следующего:
Каждый обсуждается более подробно в следующих разделах.
<?import javafx.scene.control.*?> <Button text="Click Me!"/>
<Rectangle fx:id="rectangle" x="10" y="10" width="320" height="240" fill="#ff0000"/>
В отличие от элементов свойства, которые применяются, поскольку они обрабатываются, не применяются атрибуты свойства, пока закрывающий тэг их соответствующего элемента не достигается. Это делается прежде всего, чтобы облегчить случай, где значение атрибута зависит от некоторой информации, которая не будет доступна, пока контент элемента не был полностью обработан (например, выбранные индексируют управления TabPane, которое не может быть установлено, пока все вкладки не были добавлены).
Другое основное отличие между атрибутами свойства и элементами свойства в FXML - то, что атрибуты поддерживают много "операторов разрешения", которые расширяют их функциональность. Следующие операторы поддерживаются и обсуждаются более подробно ниже:
Например, следующая разметка создает ImageView и заполняет его с данными изображения от my_image.png, который, как предполагается, располагается в пути относительно текущего файла FXML:
<ImageView> <image> <Image url="@my_image.png"/> </image> </ImageView>
Так как Изображение является неизменным объектом, разработчик обязан создавать его. Альтернативно, если Изображение должно было определить valueOf (URL) метод фабрики, представление изображения могло бы быть заполнено следующим образом:
<ImageView image="@my_image.png"/>
Значение атрибута "изображения" было бы преобразовано в URL загрузчиком FXML, затем принуждало к Изображению, используя valueOf () метод.
Отметьте, что пробельные значения в URL должны быть закодированы; например, чтобы отослать к файлу, названному "Мой Image.png", документ FXML должен содержать следующее:
<Image url="@My%20Image.png"/>
вместо:
<Image url="@My Image.png"/>
В FXML замена ресурса может быть выполнена во время загрузки в целях локализации. Когда обеспечено экземпляром java.util. ResourceBundle, загрузчик FXML заменит экземпляры имен ресурса с их специфичными для локали значениями. Имена ресурса идентифицируются префиксом "%", как показано ниже:
<Label text="%myText"/>
Если загрузчику дают пакет ресурса, определенный следующим образом:
myText = This is the text!
вывод загрузчика FXML был бы экземпляром Метки, содержащим текст, "Это - текст!".
<fx:define> <ToggleGroup fx:id="myToggleGroup"/> </fx:define> ... <RadioButton text="A" toggleGroup="$myToggleGroup"/> <RadioButton text="B" toggleGroup="$myToggleGroup"/> <RadioButton text="C" toggleGroup="$myToggleGroup"/>
<Label text="\$10.00"/>
Переменные атрибута как показано выше разрешаются однажды во время загрузки. Более поздние обновления к значению переменных автоматически не отражаются ни в каких свойствах, которым было присвоено значение. Во многих случаях это достаточно; однако, часто удобно "связать" значение свойства с переменной, или выражение так, что изменяется на переменную, автоматически распространяются к целевому свойству. Привязка выражения может использоваться с этой целью.
<TextField fx:id="textField"/> <Label text="${textField.text}"/>
Поскольку пользователь вводит текстовый ввод, текстовый контент метки будет автоматически обновлен.
Только простые выражения, которые решают к значениям свойств или переменным страницы, в настоящий момент поддерживаются. Поддержка более сложных выражений, включающих булевы или другие операторы, может быть добавлена в будущем.
<GridPane> <children> <Label text="My Label" GridPane.rowIndex="0" GridPane.columnIndex="0"/> </children> </TabPane>
Атрибуты обработчика событий являются удобным средством присоединения поведений, чтобы задокументировать элементы. Любой class, который определяет setOnEvent () метод, может быть присвоен обработчик событий в разметке, как может любое заметное свойство (через атрибут "onPropertyChange").
FXML поддерживает два типа атрибутов обработчика событий: обработчики событий сценария и обработчики событий метода контроллера. Каждый обсуждается ниже.
<?language javascript?> ... <VBox> <children> <Button text="Click Me!" onAction="java.lang.System.out.println('You clicked me!');"/> </children> </VBox>
Обработчик событий метода контроллера является методом, определенным "контроллером" документа. Контроллер является объектом, который связывается с десериализованным содержанием документа FXML и ответственен за координирование поведений объектов (часто элементы пользовательского интерфейса) определенный документом.
<VBox fx:controller="com.foo.MyController" xmlns:fx="http://javafx.com/fxml"> <children> <Button text="Click Me!" onAction="#handleButtonAction"/> </children> </VBox>
package com.foo; public class MyController { public void handleButtonAction(ActionEvent event) { System.out.println("You clicked me!"); } }
handleButtonAction () вызовут, когда пользователь нажмет кнопку, и текст, "Вы щелкнули по мне!" будет записан консоли.
Контроллеры обсуждаются более подробно в более позднем разделе.
Например, следующая разметка определяет функцию, вызванную handleButtonAction (), который вызывает обработчик действия, присоединенный к элементу Кнопки:
<?language javascript?> <?import javafx.scene.control.*?> <?import javafx.scene.layout.*?> <VBox xmlns:fx="http://javafx.com/fxml"> <fx:script> importClass(java.lang.System); function handleButtonAction(event) { 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"/> <children> <Button text="Click Me!" onAction="handleButtonAction(event);"/> </children> </VBox>
importClass(java.lang.System); function handleButtonAction(event) { System.out.println('You clicked me!'); }
Часто предпочтительно разделить код от разметки таким образом, так как много текстовых редакторов поддерживают подсветку синтаксиса для различных языков сценариев, поддерживаемых JVM. Это может также помочь улучшить удобочитаемость исходного кода и разметки.
Отметьте, что блоки сценария не ограничиваются определением функций обработчика событий. Код сценария выполняется, поскольку он обрабатывается, таким образом, он может также использоваться, чтобы динамически сконфигурировать структуру получающегося вывода. Как простой пример, следующий FXML включает блок сценария, который определяет переменную, названную "labelText". Значение этой переменной используется, чтобы заполнить текстовое свойство экземпляра Метки:
<fx:script> var myText = "This is the text of my label."; </fx:script> ... <Label text="$myText"/>
В то время как может быть удобно записать простые обработчики событий в сценарии, или встроенном или определенном во внешних файлах, часто предпочтительно определить более сложную логику приложения на скомпилированном, языке со строгим контролем типов, таком как Java. Как обсуждено ранее, атрибут fx:controller позволяет вызывающей стороне связывать "контроллер" class с документом FXML. Контроллером является скомпилированный class, который реализует "код позади" иерархии объектов, определенной документом.
Как показано ранее контроллеры часто используются, чтобы реализовать обработчики событий для элементов пользовательского интерфейса, определенных в разметке:
<VBox fx:controller="com.foo.MyController" xmlns:fx="http://javafx.com/fxml"> <children> <Button text="Click Me!" onAction="#handleButtonAction"/> </children> </VBox>
package com.foo; public class MyController { public void handleButtonAction(ActionEvent event) { System.out.println("You clicked me!"); } }
public void 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!"); } }); } }
Например, контроллеры от предыдущих примеров могли быть переписаны следующим образом:
package com.foo; public class MyController { @FXML private void handleButtonAction(ActionEvent event) { System.out.println("You clicked me!"); } }
package com.foo; 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!"); } }); } }
В первой версии handleButtonAction () тегируется с @FXML, чтобы позволить разметке, определенной в документе контроллера вызывать это. Во втором примере поле кнопки аннотируется, чтобы позволить загрузчику устанавливать свое значение. Инициализирование () метод так же аннотируется.
<VBox fx:controller="com.foo.MainController"> <fx:include fx:id="dialog" source="dialog.fxml"/> ... </VBox>
public class MainController extends Controller { @FXML private Window dialog; @FXML private DialogController dialogController; ... }
когда контроллер инициализирует (), метод вызывают, диалоговое поле будет содержать корневой элемент, загруженный из "dialog.fxml", включают, и dialogController поле будет содержать контроллер include. Основной контроллер может тогда вызвать методы на включенный контроллер, чтобы заполнить и показать диалоговое окно, например.
class FXMLLoader ответственен за то, что фактически загрузил исходный файл FXML и возвратил получающийся граф объектов. Например, следующий код загружает файл FXML из расположения на пути к классу относительно загружающегося class и локализует это с пакетом ресурса, названным "com.foo.example". Тип корневого элемента, как предполагается, является подклассом javafx.scene.layout. Область, и документ, как предполагается, определяют контроллер типа MyController:
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();
Например, следующая разметка определяет структуру простого пользовательского элемента управления, содержащего TextField и экземпляр Кнопки. Корневой контейнер определяется как экземпляр javafx.scene.layout. VBox:
<?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>
Как отмечалось ранее <fx:root> тег создает ссылку на ранее определенный корневой элемент. Значение этого элемента получается, вызывая getRoot () метод FXMLLoader.
В следующем примере CustomControl class расширяет VBox (тип, объявленный <fx:root> элементом), и принимается и как корень и как контроллер документа FXML в его конструкторе. Когда документ будет загружен, содержание CustomControl будет заполнено с содержанием предыдущего документа FXML:
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!"); } }
Теперь, вызывающие стороны могут использовать экземпляры этого управления в коде или в разметке, точно так же как любое другое управление; например:
HBox hbox = new HBox(); CustomControl customControl = new CustomControl(); customControl.setText("Hello World!"); hbox.getChildren().add(customControl);
<HBox> <CustomControl text="Hello World!"/> </HBox>
Copyright (c) 2008, 2013, Oracle и/или его филиалы. Все права защищены. Использование подвергается