Spec-Zone .ru
спецификации, руководства, описания, API


Выпуск: JavaFX 2.2

Введение в FXML

Последнее обновление: 21.06.2012

Содержание

Краткий обзор

FXML является scriptable, основанным на XML языком разметки для того, чтобы создать графы объектов Java. Это обеспечивает удобную альтернативу построению таких графиков в процедурном коде, и идеально подходит для определения пользовательского интерфейса приложения JavaFX, так как иерархическая структура XML-документа близко параллельна структуре графика сцены JavaFX.

Этот документ представляет язык разметки FXML и объясняет, как это может использоваться, чтобы упростить разработку приложений JavaFX.

Элементы

В FXML элемент XML представляет одно из следующего:

Экземпляры класса, свойства экземпляра, статические свойства, и определяют блоки, обсуждаются в этом разделе ниже. Сценарии обсуждаются в более позднем разделе.

Элементы Экземпляра класса

Экземпляры класса могут быть созданы в FXML несколькими способами. Наиболее распространенное через элементы объявления экземпляра, которые просто создают новый экземпляр class по имени. Другие способы создать экземпляры class включают ссылающиеся существующие значения, копируя существующие значения, и включая внешние файлы FXML. Каждый обсуждается более подробно ниже.

Объявления экземпляра

Если имя тега элемента начинается с прописной буквы (и это не "статический" метод set свойства, описал позже), это считают объявлением экземпляра. Когда загрузчик FXML (также представлял позже) встречается с таким элементом, он создает экземпляр того class.

Как в Java, имена class могут быть полностью определены (включая имя пакета), или они могут быть импортированы, используя инструкцию обработки "импорта" (PI). Например, следующий PI импортирует javafx.scene.control. Маркируйте class в текущее пространство имен документа FXML:

<?import javafx.scene.control.Label?>

Этот PI импортирует все классы из javafx.scene.control пакета в текущее пространство имен:

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

Любой class, который придерживается конструктора JavaBean и соглашений о присвоении имен свойства, можно с готовностью инстанцировать и сконфигурировал использование FXML. Следующее является простым, но полным примером, который создает экземпляр javafx.scene.control. Метка и наборы ее "текстовое" свойство к "Привет, Мир!":

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

Отметьте, что "текстовое" свойство Метки в этом примере устанавливается, используя атрибут XML. Свойства могут также быть установлены, используя вложенные элементы свойства. Элементы свойства обсуждаются более подробно позже в этом разделе. Атрибуты свойства обсуждаются в более позднем разделе.

Классы, которые не соответствуют Бобовым соглашениям, могут также быть созданы в FXML, используя объект, названный "разработчиком". Разработчики обсуждаются более подробно позже.

Карты

Внутренне, загрузчик FXML использует экземпляр com.sun.javafx.fxml. BeanAdapter, чтобы обернуть инстанцированный объект и вызвать его методы метода set. Этот (в настоящий момент) частный class реализует java.util. Интерфейс карты и позволяет вызывающей стороне получать и устанавливать Бобовые значения свойств как пары ключ/значение.

Если элемент представляет тип, который уже реализует Карту (такую как java.util. HashMap), это не обертывается и добираемое () и помещается (), методы вызываются непосредственно. Например, следующий FXML создает экземпляр HashMap и устанавливает его "foo", и "панель" оценивает "123" и "456", соответственно:

<HashMap foo="123" bar="456"/>
fx:value

Атрибут fx:value может использоваться, чтобы инициализировать экземпляр типа, который не имеет конструктора по умолчанию, но обеспечивает статический valueOf (Строка) метод. Например, java.lang. Строка так же как каждый из примитивных типов обертки определяет valueOf () метод и может быть создана в FXML следующим образом:

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

Пользовательские классы, которые определяют статический valueOf (Строка) метод, могут также быть созданы этот путь.

fx:factory

Атрибут fx:factory является другим средством создания объектов, у классов которых нет конструктора по умолчанию. Значение атрибута является именем статического, метода фабрики без аргументов для того, чтобы произвести экземпляры class. Например, следующая разметка создает экземпляр заметного списка массива, заполненного с тремя строковыми значениями:

<FXCollections fx:factory="observableArrayList">
    <String fx:value="A"/>
    <String fx:value="B"/>
    <String fx:value="C"/>
</FXCollections>
Разработчики

Третье средство создания экземпляров классов, которые не соответствуют Бобовым соглашениям (таким как те, которые представляют неизменные значения), является "разработчиком". Делегаты шаблона разработки разработчика возражают конструкции против изменчивого помощника class (названный "разработчиком"), который ответственен за производственные экземпляры неизменного типа.

Поддержка разработчика в 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>

<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> также поддерживает атрибуты для того, чтобы определить имя пакета ресурса, который должен использоваться, чтобы локализовать включенный контент, так же как набор символов, используемый, чтобы закодировать исходный файл. Разрешение ресурса обсуждается в более позднем разделе.

<fx:constant>

<fx:constant> элемент создает ссылку на постоянный class. Например, следующая разметка устанавливает значение "minWidth" свойства aButton экземпляра к значению константы NEGATIVE_INFINITY, определенной java.lang. Двойной class:

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

<fx:reference>

<fx:reference> элемент создает новую ссылку на существующий элемент. Везде, где этот тег появляется, он будет эффективно заменен значением именованного элемента. Это используется в соединении или с атрибутом fx:id или со сценарием переменные, обе из которых обсуждаются более подробно в более поздних разделах. "Исходный" атрибут <fx:reference> элемента определяет имя объекта, к которому обратится новый элемент.

Например, следующая разметка присваивает ранее определенный экземпляр Изображения, названный "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>

Для большинства других случаев, используя атрибут более просто и более краток.

<fx:copy>

<fx:copy> элемент создает копию существующего элемента. Как <fx:reference>, это используется с атрибутом fx:id или переменной сценария. "Исходный" атрибут элемента определяет имя объекта, который будет скопирован. Исходный тип должен определить конструктора копии, который будет использоваться, чтобы создать копию с исходного значения.

В настоящее время никакие классы платформы JavaFX не предоставляют такому конструктору копии, таким образом, этот элемент обеспечивается прежде всего для использования разработчиками приложений. Это может измениться в будущем выпуске.

<fx:root>

<fx:root> элемент создает ссылку на ранее определенный корневой элемент. Это только допустимо как корневой узел документа FXML. <fx:root> используется прежде всего, создавая пользовательские элементы управления, которые поддерживаются разметкой FXML. Это обсуждается более подробно в разделе FXMLLoader.

Элементы свойства

Элементы, имена тега которых начинаются со строчной буквы, представляют объектные свойства. Элемент свойства может представить одно из следующего:

Методы set свойства

Если элемент представляет метод set свойства, содержание элемента (который должен быть или текстовым узлом или вложенным элементом экземпляра class), передаются как значение к методу set для свойства.

Например, следующий FXML создает экземпляр Метки class и устанавливает значение "текстового" свойства метки к "Привет, Мир!":

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

Это приводит к тому же самому результату как более ранний пример, который использовал атрибут, чтобы установить "текстовое" свойство:

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

Элементы свойства обычно используются, когда значение свойства является составным типом, который не может быть представлен, используя простое основанное на операция со строками значение атрибута, или когда символьная длина значения является такой длинной, что, определяя у этого как атрибут было бы негативное воздействие на удобочитаемости.

Введите Приведение

FXML использует "приведение типа", чтобы преобразовать значения свойств в соответствующий тип как необходимый. Приведение типа требуется, потому что единственные типы данных, поддерживаемые XML, являются элементами, текстом, и атрибутами (чьи значения являются также текстом). Однако, Java поддерживает много различных типов данных включая встроенные примитивные типы значения так же как расширяемые ссылочные типы.

Загрузчик FXML использует принуждение () метод BeanAdapter, чтобы выполнить любые необходимые преобразования типов. Этот метод способен к выполнению основных преобразований типа примитива, таких как Строка к булеву или международному, чтобы удвоиться, и также преобразует Строку в Класс или Строку к Перечислению. Дополнительные преобразования могут быть реализованы, определяя статический valueOf () метод на целевом типе.

Свойства Списка только для чтения

Свойство списка только для чтения является свойством Bean, метод get которого возвращает экземпляр java.util. Перечислите и не имеет никакого соответствующего метода метода set. Содержание элемента списка только для чтения автоматически добавляется к списку, поскольку они обрабатываются.

Например, "дочернее" свойство 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 ().

Свойства Карты только для чтения

Свойство карты только для чтения является бобовым свойством, метод get которого возвращает экземпляр java.util. Отобразитесь и не имеет никакого соответствующего метода метода set. Атрибуты элемента карты только для чтения применяются к карте, когда закрывающий тэг обрабатывается.

Свойство "свойств" javafx.scene. Узел является примером свойства карты только для чтения. Следующая разметка устанавливает свойства "foo" и "панели" экземпляра Метки к "123" и "456", соответственно:

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

Отметьте, что свойство только для чтения, типом которого не является ни Список, ни Карта, будет обработано, как будто это была карта только для чтения. Возвращаемое значение метода метода get будет обернуто в BeanAdapter и может использоваться таким же образом в качестве любой другой карты только для чтения.

Свойства значения по умолчанию

class может определить "свойство значения по умолчанию" использование @DefaultProperty аннотации, определенной в javafx.beans пакете. Если существующий, подэлемент, представляющий свойство значения по умолчанию, может быть опущен от разметки.

Например, с тех пор 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, к которому они применяются, но определяются другим class (часто, родительский контейнер управления).

Статические свойства снабжаются префиксом имя 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, определяют подобные свойства.

Как со свойствами экземпляра, обычно используются статические элементы свойства, когда значение свойства не может быть эффективно представлено значением атрибута. Иначе, статические атрибуты свойства (обсужденный в более позднем разделе) обычно произведут более краткую и читаемую разметку.

Определите Блоки

<fx:define> элемент используется, чтобы создать объекты, которые существуют за пределами иерархии объектов, но, возможно, должны быть упомянуты в другом месте.

Например, работая с переключателями, распространено определить 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 может представить одно из следующего:

Каждый обсуждается более подробно в следующих разделах.

Свойства экземпляра

Как элементы свойства, атрибуты могут также использоваться, чтобы сконфигурировать свойства экземпляра class. Например, следующая разметка создает Кнопку, текстовые чтения которой "Щелкают по Мне!":

<?import javafx.scene.control.*?>
<Button text="Click Me!"/>

Как с элементами свойства, свойство приписывает приведение типа поддержки. То, когда следующая разметка будет обработана, "x", "y", "width", и значения "height" будут преобразованы в, удваивается, и значение "заливки" будет преобразовано в Цвет:

<Rectangle fx:id="rectangle" x="10" y="10" width="320" height="240"
    fill="#ff0000"/>

В отличие от элементов свойства, которые применяются, поскольку они обрабатываются, не применяются атрибуты свойства, пока закрывающий тэг их соответствующего элемента не достигается. Это делается прежде всего, чтобы облегчить случай, где значение атрибута зависит от некоторой информации, которая не будет доступна, пока контент элемента не был полностью обработан (например, выбранные индексируют управления TabPane, которое не может быть установлено, пока все вкладки не были добавлены).

Другое основное отличие между атрибутами свойства и элементами свойства в FXML - то, что атрибуты поддерживают много "операторов разрешения", которые расширяют их функциональность. Следующие операторы поддерживаются и обсуждаются более подробно ниже:

Разрешение расположения

Как строки, атрибуты XML не могут исходно представить введенную информацию о расположении, такую как URL. Однако, часто необходимо определить такие расположения в разметке; например, источник ресурса изображения. Оператор разрешения расположения (представленный префикс к значению атрибута) используется, чтобы определить, что значение атрибута должно быть обработано как расположение относительно текущего файла, а не простой строки.

Например, следующая разметка создает 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 был бы экземпляром Метки, содержащим текст, "Это - текст!".

Переменное Разрешение

Документ FXML определяет переменное пространство имен, в котором названный элементами и переменными сценария может быть однозначно определен. Переменный оператор разрешения позволяет вызывающей стороне заменять значение атрибута экземпляром именованного объекта прежде, чем соответствующий метод метода set будет вызван. Переменные ссылки идентифицируются префиксом "$", как показано ниже:

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

Присвоение значения fx:id к элементу создает переменную в пространстве имен документа, которое может позже быть упомянуто переменной, разыменовывают атрибуты, такие как атрибут "toggleGroup", показанный выше, или в коде сценария, обсужденном в более позднем разделе. Дополнительно, если тип объекта определит свойство "идентификатора", то это значение также передадут к объектам setId () метод.

Escape-последовательности

Если значение атрибута начинается с одного из префиксов разрешения ресурса, символа можно оставить, предварительно ожидая это с ведущей наклонной чертой влево (" \") символ. Например, следующая разметка создает экземпляр Метки, текст которого читает" 10,00" $:

<Label text="\$10.00"/>

Привязка выражения

Переменные атрибута как показано выше разрешаются однажды во время загрузки. Более поздние обновления к значению переменных автоматически не отражаются ни в каких свойствах, которым было присвоено значение. Во многих случаях это достаточно; однако, часто удобно "связать" значение свойства с переменной, или выражение так, что изменяется на переменную, автоматически распространяются к целевому свойству. Привязка выражения может использоваться с этой целью.

Выражение, связывающее также, начинается с переменного оператора разрешения, но сопровождается рядом изогнутых фигурных скобок, которые обертывают значение выражения. Например, следующая разметка связывает значение текстового входного "текстового" свойства к "текстовому" свойству экземпляра Метки:

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

Поскольку пользователь вводит текстовый ввод, текстовый контент метки будет автоматически обновлен.

Только простые выражения, которые решают к значениям свойств или переменным страницы, в настоящий момент поддерживаются. Поддержка более сложных выражений, включающих булевы или другие операторы, может быть добавлена в будущем.

Статические Свойства

Атрибуты, представляющие статические свойства, обрабатываются так же к статическим элементам свойства и используют подобный синтаксис. Например, более ранняя разметка GridPane, показанная ранее, чтобы демонстрировать статические элементы свойства, могла быть переписана следующим образом:

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

В дополнение к тому, чтобы быть более краткими, статическими атрибутами свойства, как атрибуты свойства экземпляра, расположение поддержки, ресурс, и переменные операторы разрешения, единственное ограничение, являющееся этим, не возможно создать привязку выражения со статическим свойством.

Обработчики событий

Атрибуты обработчика событий являются удобным средством присоединения поведений, чтобы задокументировать элементы. Любой class, который определяет setOnEvent () метод, может быть присвоен обработчик событий в разметке, как может любое заметное свойство (через атрибут "onPropertyChange").

FXML поддерживает два типа атрибутов обработчика событий: обработчики событий сценария и обработчики событий метода контроллера. Каждый обсуждается ниже.

Обработчики событий сценария

Обработчик событий сценария является обработчиком событий, который выполняет код сценария, когда событие запускается, подобно обработчикам событий в HTML. Например, следующий основанный на сценарии обработчик для "onAction" события кнопки использует JavaScript, чтобы записать текст, "Вы щелкнули по мне!" к консоли, когда пользователь нажимает кнопку:

<?language javascript?>
...

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

Отметьте использование инструкции обработки языка в начале фрагмента кода. Этот PI говорит загрузчик FXML, какой язык сценариев должен использоваться, чтобы выполнить обработчик событий. Язык страницы должен быть определен всякий раз, когда встроенный сценарий используется в документе FXML, и может только быть определен однажды на документ. Однако, это не применяется к внешним сценариям, которые могут быть реализованы, используя любое число поддерживаемых языков сценариев. Сценарии обсуждаются более подробно в следующем разделе.

Обработчики событий Метода контроллера

Обработчик событий метода контроллера является методом, определенным "контроллером" документа. Контроллер является объектом, который связывается с десериализованным содержанием документа FXML и ответственен за координирование поведений объектов (часто элементы пользовательского интерфейса) определенный документом.

Обработчик событий метода контроллера определяется ведущим символом хеша, сопровождаемым именем метода обработчика. Например:

<VBox fx:controller="com.foo.MyController"
    xmlns:fx="http://javafx.com/fxml">
    <children>
        <Button text="Click Me!" onAction="#handleButtonAction"/>
    </children>
</VBox>

Отметьте использование атрибута fx:controller на корневом элементе. Этот атрибут используется, чтобы связать контроллер class с документом. Если MyController определяется следующим образом:

package com.foo;

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

handleButtonAction () вызовут, когда пользователь нажмет кнопку, и текст, "Вы щелкнули по мне!" будет записан консоли.

Вообще, метод обработчика должен соответствовать подписи стандартного обработчика событий; то есть, это должно взять единственный параметр типа, который расширяет javafx.event. Событие и должно возвратиться пусто (подобный делегату события в C#). Параметр события часто переносит важную и полезную информацию о природе события; однако, это является дополнительным и может быть опущено при желании.

Контроллеры обсуждаются более подробно в более позднем разделе.

Сценарии

<fx:script> тег позволяет вызывающей стороне импортировать код сценариев в или встраивать сценарий в пределах файла FXML. Любой язык сценариев JVM может использоваться, включая JavaScript, Groovy, и Clojure, среди других. Код сценария часто используется, чтобы определить обработчики событий непосредственно в разметке или в связанном исходном файле, так как обработчики событий могут часто писаться более кратко в более свободно введенных языках сценариев, чем они могут в статически типизированном языке, таком как Java.

Например, следующая разметка определяет функцию, вызванную 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>

Щелчок по кнопке инициировал обработчик событий, который вызывает функцию, производя выводит идентичный предыдущим примерам.

Код сценария может также быть определен во внешних файлах. Предыдущий пример мог быть разделен на файл FXML и исходный файл JavaScript без различия в функциональности:

example.fxml
<?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>
example.js
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();

Это позволяет реализации class, чтобы выполнить любую необходимую последующую обработку на контенте. Это также предоставляет контроллеру доступ к ресурсам, которые использовались, чтобы загрузить документ и расположение, которое использовалось, чтобы разрешить относительные пути в пределах документа (обычно эквивалентный расположению документа непосредственно).

Например, следующий код определяет инициализирование () метод, который присоединяет обработчик действия к кнопке в коде, а не через атрибут обработчика событий, как был сделан в предыдущем примере. Переменная экземпляра кнопки вводится загрузчиком, поскольку документ читается. Получающееся поведение приложения идентично:

<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!");
            }
        });
    }
}

@FXML

Отметьте, что в предыдущих примерах задействованные поля контроллера и методы обработчика событий были объявлены как общественность, таким образом, они могут быть установлены или вызваны загрузчиком. Практически, это - не часто проблема, так как контроллер обычно только видим к загрузчику FXML, который создает его. Однако, для разработчиков, которые предпочитают более ограниченную видимость для полей контроллера или методов обработчика, javafx.fxml. Аннотация FXML может использоваться. Эта аннотация отмечает защищенный или частный элемент class как доступный для FXML.

Например, контроллеры от предыдущих примеров могли быть переписаны следующим образом:

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, чтобы позволить разметке, определенной в документе контроллера вызывать это. Во втором примере поле кнопки аннотируется, чтобы позволить загрузчику устанавливать свое значение. Инициализирование () метод так же аннотируется.

Отметьте, что @FXML аннотация может в настоящий момент только использоваться с доверяемым кодом. Поскольку загрузчик FXML полагается на отражение к полям элемента множества, и вызовите задействованные методы, это должно вызвать setAccessible () на любом непубличном Поле. setAccessible () является привилегированной работой, которая может только быть выполнена в безопасном контексте. Это может измениться в будущем выпуске.

Вложенные Контроллеры

Экземпляры контроллера для вложенных документов FXML, загруженных через <fx:include> элемент, отображаются непосредственно на задействованные поля включения контроллера. Это позволяет разработчику легко получать доступ к функциональности, определенной включением (таким как диалоговое окно, представленное контроллером главного окна приложения). Например, учитывая следующий код:

main_window_content.fxml
<VBox fx:controller="com.foo.MainController">
   <fx:include fx:id="dialog" source="dialog.fxml"/>
   ...
</VBox>
MainController.java
public class MainController extends Controller {
    @FXML private Window dialog;
    @FXML private DialogController dialogController;

    ...
}

когда контроллер инициализирует (), метод вызывают, диалоговое поле будет содержать корневой элемент, загруженный из "dialog.fxml", включают, и dialogController поле будет содержать контроллер include. Основной контроллер может тогда вызвать методы на включенный контроллер, чтобы заполнить и показать диалоговое окно, например.

FXMLLoader

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();

Отметьте, что вывод FXMLLoader#load () работа является иерархией экземпляра, которая отражает фактические именованные классы в документе, не org.w3c.dom узлы, представляющие те классы. Внутренне, FXMLLoader использует javax.xml.stream API (также известный как API Потоковой передачи для XML, или StAX), чтобы загрузить документ FXML. StAX является чрезвычайно эффективным основанным на событии XML, анализирующим API, который концептуально подобен его предшественнику W3C, SAX. Это позволяет документу FXML быть обработанным в единственной передаче, вместо того, чтобы загруженным в промежуточное звено структура ДОМА и затем постобработанным.

Пользовательские Компоненты

setRoot () и setController () методы FXMLLoader позволяют вызывающей стороне вводить корень документа и значения контроллера, соответственно, в пространство имен документа, вместо того, чтобы делегировать создание этих значений к FXMLLoader непосредственно. Это позволяет разработчику легко создавать допускающие повторное использование средства управления, которые внутренне реализуются, используя разметку, но (с точки зрения API) появляются тождественно к средствам управления, реализованным программно.

Например, следующая разметка определяет структуру простого пользовательского элемента управления, содержащего 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. До вызова загрузки (), вызывающая сторона должна определить это значение через звонок setRoot (). Вызывающая сторона может так же обеспечить значение для контроллера документа, вызывая setController (), который устанавливает значение, которое будет использоваться в качестве контроллера документа, когда документ будет считан. Эти два метода обычно используются вместе, создавая пользовательские FXML-на-основе компоненты.

В следующем примере 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!");
    }
}

Теперь, вызывающие стороны могут использовать экземпляры этого управления в коде или в разметке, точно так же как любое другое управление; например:

Java
HBox hbox = new HBox();
CustomControl customControl = new CustomControl();
customControl.setText("Hello World!");
hbox.getChildren().add(customControl);
FXML
<HBox>
    <CustomControl text="Hello World!"/>
</HBox>

Copyright (c) 2008, 2013, Oracle и/или его филиалы. Все права защищены. Использование подвергается срокам действия лицензии.