На JavaOne 2011 было объявлено о выпуске финальной версии JavaFX 2.0. Рассмотрим из чего оно состояит и какие средства предлагает.
![image](http://javafx.me/files/injfx.jpg)
Создадим и запустим первое приложение на JavaFX. Для этого нам понадобится JavaFX 2.0 SDK и последний Netbeans. О настройке JavaFX в Netbeans можно прочитать на странице http://netbeans.org/kb/docs/java/javafx-setup.html.
Запускаем Netbeans, выбираем из меню File/New Project, в диалоге выбираем категорию JavaFX и тип проекта JavaFX Application. Будет создан проект с одной тестовой формой как на картинке ниже (можно назвать проект HelloJavaFX или как-то иначе). Код класса формы:
результат:
![image](http://javafx.me/files/injfxsplash.jpg)
Посмотрим что у нас появится в папке dist после компиляции. Там будут следующие файлы:
— папка web-files — содержит картинки для запуска в виде апплета
— HelloJavaFX.html — страница с встроенным апплетом приложения
— HelloJavaFX.jar — приложение для запуска обычным двойным щелчком мыши
— HelloJavaFX.jnlp — описатель запуска через WebStart
Нас интересует само приложение HelloJavaFX.jar. Откроем его любым архиватором (.jar это обычный .zip-архив) и посмотрим на манифест. Главная строка запуска:
говорит о том что в каждое JavaFX-приложение Netbeans'ом добавляется класс-стартер com.javafx.main.Main, который инициализирует все библиотеки JavaFX и запускает само приложение. Имя главного класс берётся из поля JavaFX-Application-Class, в нашем случает это hellojavafx.HelloJavaFX
Ничего необычного. На данный момент JavaFX это просто набор библиотек, функции которых можно использовать из Java-кода.
Рассмотрим пример Swing-формы со встроенным JavaFX-компонентом. Создадим в Netbeans новый проект и добавим в него ссылку на Runtime-библиотеку JavaFX (по умолчанию она находится в файле C:\Program Files\Oracle\JavaFX Runtime 2.0\lib\jfxrt.jar).
После подключения Runtime, можно встраивать любые JavaFX-компоненты с помощью класса JFXPanel. Дабавим текстовый редактор с помощью следующего кода:
В результате получится такая форма:
![image](http://javafx.me/files/injfxedtr.jpg)
Как видно по коду кнопки Read, мы в любой момент можем получить доступ к данным в текстовом редакторе. Для запуска такого приложения мы должны добавить в class-path путь к Runtime-библиотеки JavaFX, например так:
Всё достаточно тривиально и не отличается от использования других библиотек в Java-проектах.
С возможностями JavaFX можно ознакомиться на странице платформы. В API есть набор классов для рисования примитивов, графиков, набор компонентов GUI с собственным оформлением. Наконец-то появился компонент веб-браузера и текстовый редактор с возможностью форматирования.
На странице http://www.oracle.com/technetwork/java/javafx/overview/index.html можно запустить демо-приложение Ensemble (это аналог Flex Component Explorer).
![image](http://javafx.me/files/infxens.jpg)
Binding (связывание) предназначен для связывания свойств объектов. Например вы можете привязать координаты кнопки к ширине окна и в результате при изменении размеров формы, переместится и привязанная кнопка.
Рассмотрим на примере:
Результат:
![image](http://javafx.me/files/injfxbind.gif)
Строка с кодом
создаёт переменную db и привязывает её значение к ширине формы минус 150 пикселов. К сожалению мы не можем просто привязать координаты кнопки к этой переменной (типа btn.layoutX.bind(db); что было бы очевидно и удобно). Поэтому к созданной переменной надо добавить Listener, в котором и обновлять координаты кнопки:
Кроме того, binding накладывает дополнительные ограничения — если вы привяжете свойство к переменной то не сможете изменить простым присваиванием, будет выброшено исключение во время работы приложения.
Сам код API чрезмерно раздут, например класс SimpleDoubleProperty имеет иерархию наследования из шести классов и имплементирует девять интерфейсов. Это новое понимание характеристики simple.
В результате хорошая идея выглядит не очень привлекательно. Много кода, неявные ошибки. Хотя простая и понятная реализация связывания есть для многих языков и библиотек, в том числе и для Swing.
Оформление интерфейса можно задавать с помощью CSS. Для этого нужно создать описание стилей, например такое:
— стиль cssbutton задаёт шрифт, отступы, заливку и эффект тени. Далее нужно подключить файл стилей к сцене:
и добавить стиль к компоненту по имени:
Кнопка будет выглядеть примерно так:
![image](http://javafx.me/files/ijfxcss.jpg)
Описание доступных в CSS свойств можно прочитать на странице документации.
Не очень понятно зачем вообще нужно задавать оформление стилями. Всё что можно задать стилями можно сделать и в коде, в CSS нельзя использовать переменные или вычисления, нельзя создавать новые свойства, стили сложно отлаживать.
Компоновку форм можно задать в отдельном файле FXML и при старте приложения загрузить из него. Такой подход используется во многих средах разработки.
В Netbeans для этих целей предлагается создать проект с типом JavaFX FXML Application. Будет создана начальная форма примерно такого содержания:
Аннотация @FXML служит для обозначения переменных и функций доступных при загрузке из FXML-файла. Сам файл выглядит примерно так:
Как видно в примере, и метод handleButtonAction и свойство label заданные в коде, используются внутри FXML-описания формы.
Загрузка FXML-формы при старте приложения вызывается примерно так:
Каких-то преимуществ подобное создание GUI не даёт. Визуального редактора нет, а править руками одинаково затратно как Java-код, так и FXML-описание.
Форморисовалка есть в Visual Studio для VB и C#, в Adobe Flex, в Oracle JBuilder есть прекрасный редактор для Swing. Для JavaFX визульный редактор был объявлен ещё 2 года назад. Можно даже видео с ним посмотреть на странице http://www.flickr.com/photos/douglasbullard/3609213630/in/photostream/.
Но пока публичного релиза не было и неизвестно когда будет.
Общая оценка скорей всего неудовлетворительная. Демо-приложения тормозят, внешний вид компонентов уступает Macintosh Aqua, Adone Flex или Microsoft Metro. Первая версия JavaFX появилась ещё в далёком 2008 году но Sun так и не смог довести технологию до ума.
Тем не менее, на последней JavaOne о JavaFX говорилось очень много. Будем надеяться что Oracle железной рукой направит разработчиков в нужное русло и заставит выдать наконец-то рабочий инструмент весто обещаний.
![image](http://javafx.me/files/injfx.jpg)
Hello JavaFX
Создадим и запустим первое приложение на JavaFX. Для этого нам понадобится JavaFX 2.0 SDK и последний Netbeans. О настройке JavaFX в Netbeans можно прочитать на странице http://netbeans.org/kb/docs/java/javafx-setup.html.
Запускаем Netbeans, выбираем из меню File/New Project, в диалоге выбираем категорию JavaFX и тип проекта JavaFX Application. Будет создан проект с одной тестовой формой как на картинке ниже (можно назвать проект HelloJavaFX или как-то иначе). Код класса формы:
package hellojavafx;
import javafx.application.*;
import javafx.event.*;
import javafx.scene.*;
import javafx.scene.control.*;
import javafx.stage.*;
public class HelloJavaFX extends Application {
public static void main(String[] args) {
Application.launch(args);
}
@Override public void start(Stage primaryStage) {
primaryStage.setTitle("Hello World");
Group root = new Group();
Scene scene = new Scene(root, 300, 250);
Button btn = new Button();
btn.setLayoutX(100);
btn.setLayoutY(80);
btn.setText("Hello World");
btn.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent event) {
System.out.println("Hello World");
}
});
root.getChildren().add(btn);
primaryStage.setScene(scene);
primaryStage.show();
}
}
результат:
![image](http://javafx.me/files/injfxsplash.jpg)
Посмотрим что у нас появится в папке dist после компиляции. Там будут следующие файлы:
— папка web-files — содержит картинки для запуска в виде апплета
— HelloJavaFX.html — страница с встроенным апплетом приложения
— HelloJavaFX.jar — приложение для запуска обычным двойным щелчком мыши
— HelloJavaFX.jnlp — описатель запуска через WebStart
Нас интересует само приложение HelloJavaFX.jar. Откроем его любым архиватором (.jar это обычный .zip-архив) и посмотрим на манифест. Главная строка запуска:
Main-Class: com/javafx/main/Main
говорит о том что в каждое JavaFX-приложение Netbeans'ом добавляется класс-стартер com.javafx.main.Main, который инициализирует все библиотеки JavaFX и запускает само приложение. Имя главного класс берётся из поля JavaFX-Application-Class, в нашем случает это hellojavafx.HelloJavaFX
Ничего необычного. На данный момент JavaFX это просто набор библиотек, функции которых можно использовать из Java-кода.
JavaFX в Swing
Рассмотрим пример Swing-формы со встроенным JavaFX-компонентом. Создадим в Netbeans новый проект и добавим в него ссылку на Runtime-библиотеку JavaFX (по умолчанию она находится в файле C:\Program Files\Oracle\JavaFX Runtime 2.0\lib\jfxrt.jar).
После подключения Runtime, можно встраивать любые JavaFX-компоненты с помощью класса JFXPanel. Дабавим текстовый редактор с помощью следующего кода:
package swingjavafx;
import javax.swing.*;
import java.awt.event.*;
import javafx.embed.swing.*;
import javafx.scene.*;
import javafx.application.*;
import javafx.scene.web.*;
import javafx.scene.effect.*;
public class SwingJavaFx extends JFrame {
HTMLEditor edtr;
public SwingJavaFx() {
this.setSize(600, 400);
this.setVisible(true);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLayout(null);
JButton b1 = new JButton("Read");
b1.setSize(150, 22);
b1.setLocation(10, 10);
b1.addActionListener(new ActionListener() {
@Override public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(null, edtr.getHtmlText());
}
});
this.add(b1);
final JFXPanel jfx = new JFXPanel();
jfx.setSize(560, 300);
jfx.setLocation(10, 40);
this.add(jfx);
Platform.runLater(new Runnable() {
@Override public void run() {
Group root = new Group();
Scene scene = new Scene(root, 400, 300);
jfx.setScene(scene);
javafx.scene.shape.Rectangle rctngl = new javafx.scene.shape.Rectangle();
rctngl.setTranslateX(20);
rctngl.setTranslateY(30);
rctngl.setWidth(500);
rctngl.setHeight(250);
rctngl.setEffect(new Shadow());
root.getChildren().add(rctngl);
edtr = new HTMLEditor();
edtr.setHtmlText("Blablabla");
edtr.setTranslateX(20);
edtr.setTranslateY(30);
edtr.setPrefWidth(500);
edtr.setPrefHeight(250);
root.getChildren().add(edtr);
}
});
}
public static void main(String[] args) {
new SwingJavaFx();
}
}
В результате получится такая форма:
![image](http://javafx.me/files/injfxedtr.jpg)
Как видно по коду кнопки Read, мы в любой момент можем получить доступ к данным в текстовом редакторе. Для запуска такого приложения мы должны добавить в class-path путь к Runtime-библиотеки JavaFX, например так:
java -cp %cp%;"C:\Program Files\Oracle\JavaFX Runtime 2.0\lib\jfxrt.jar";SwingJavaFx.jar swingjavafx.SwingJavaFx
Всё достаточно тривиально и не отличается от использования других библиотек в Java-проектах.
API JavaFX
С возможностями JavaFX можно ознакомиться на странице платформы. В API есть набор классов для рисования примитивов, графиков, набор компонентов GUI с собственным оформлением. Наконец-то появился компонент веб-браузера и текстовый редактор с возможностью форматирования.
На странице http://www.oracle.com/technetwork/java/javafx/overview/index.html можно запустить демо-приложение Ensemble (это аналог Flex Component Explorer).
![image](http://javafx.me/files/infxens.jpg)
Binding
Binding (связывание) предназначен для связывания свойств объектов. Например вы можете привязать координаты кнопки к ширине окна и в результате при изменении размеров формы, переместится и привязанная кнопка.
Рассмотрим на примере:
package bindingjavafx;
import javafx.application.*;
import javafx.event.*;
import javafx.scene.*;
import javafx.scene.control.*;
import javafx.stage.*;
import javafx.beans.binding.*;
import javafx.beans.value.*;
public class BindingJavaFX extends Application {
public static void main(String[] args) {
Application.launch(args);
}
@Override public void start(Stage primaryStage) {
primaryStage.setTitle("Hello World");
Group root = new Group();
final Scene scene = new Scene(root, 300, 250);
final Button btn = new Button();
btn.setLayoutX(100);
btn.setLayoutY(80);
btn.setText("Hello World");
btn.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent event) {
System.out.println("Hello World");
}
});
final DoubleBinding db = scene.widthProperty().subtract(150);
db.addListener(new javafx.beans.value.ChangeListener< Number>() {
public void changed(ObservableValue<? extends Number> ov, Number t, Number t1) {
btn.setLayoutX(db.getValue());
}
});
root.getChildren().add(btn);
primaryStage.setScene(scene);
primaryStage.show();
}
}
Результат:
![image](http://javafx.me/files/injfxbind.gif)
Строка с кодом
final DoubleBinding db = scene.widthProperty().subtract(150);
создаёт переменную db и привязывает её значение к ширине формы минус 150 пикселов. К сожалению мы не можем просто привязать координаты кнопки к этой переменной (типа btn.layoutX.bind(db); что было бы очевидно и удобно). Поэтому к созданной переменной надо добавить Listener, в котором и обновлять координаты кнопки:
db.addListener(new javafx.beans.value.ChangeListener< Number>() {
public void changed(ObservableValue<? extends Number> ov, Number t, Number t1) {
btn.setLayoutX(db.getValue());
}
});
Кроме того, binding накладывает дополнительные ограничения — если вы привяжете свойство к переменной то не сможете изменить простым присваиванием, будет выброшено исключение во время работы приложения.
Сам код API чрезмерно раздут, например класс SimpleDoubleProperty имеет иерархию наследования из шести классов и имплементирует девять интерфейсов. Это новое понимание характеристики simple.
В результате хорошая идея выглядит не очень привлекательно. Много кода, неявные ошибки. Хотя простая и понятная реализация связывания есть для многих языков и библиотек, в том числе и для Swing.
Использование CSS
Оформление интерфейса можно задавать с помощью CSS. Для этого нужно создать описание стилей, например такое:
.cssbutton {
-fx-font: 16px "Serif";
-fx-padding: 10;
-fx-background-color: #CCFF99;
-fx-effect: dropshadow( one-pass-box , black , 12 , 0.0 , 1 , 1 );
}
— стиль cssbutton задаёт шрифт, отступы, заливку и эффект тени. Далее нужно подключить файл стилей к сцене:
scene.getStylesheets().add("cssjavafx/style.css");
и добавить стиль к компоненту по имени:
btn.getStyleClass().add("cssbutton");
Кнопка будет выглядеть примерно так:
![image](http://javafx.me/files/ijfxcss.jpg)
Описание доступных в CSS свойств можно прочитать на странице документации.
Не очень понятно зачем вообще нужно задавать оформление стилями. Всё что можно задать стилями можно сделать и в коде, в CSS нельзя использовать переменные или вычисления, нельзя создавать новые свойства, стили сложно отлаживать.
Использование FXML
Компоновку форм можно задать в отдельном файле FXML и при старте приложения загрузить из него. Такой подход используется во многих средах разработки.
В Netbeans для этих целей предлагается создать проект с типом JavaFX FXML Application. Будет создана начальная форма примерно такого содержания:
package fxmljavafx;
import java.net.*;
import java.util.*;
import javafx.event.*;
import javafx.fxml.*;
import javafx.scene.control.*;
public class Sample implements Initializable {
@FXML private Label label;
@FXML private void handleButtonAction(ActionEvent event) {
System.out.println("You clicked me!");
label.setText("Hello World!");
}
@Override public void initialize(URL url, ResourceBundle rb) {
//
}
}
Аннотация @FXML служит для обозначения переменных и функций доступных при загрузке из FXML-файла. Сам файл выглядит примерно так:
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane id="AnchorPane" prefHeight="200" prefWidth="320" xmlns:fx="http://javafx.com/fxml" fx:controller="fxmljavafx.Sample">
<children>
<Button id="button" layoutX="126" layoutY="90" text="Click Me!" onAction="#handleButtonAction" fx:id="button" />
<Label id="label" layoutX="126" layoutY="120" minHeight="16" minWidth="69" prefHeight="16" prefWidth="69" fx:id="label" />
</children>
</AnchorPane>
Как видно в примере, и метод handleButtonAction и свойство label заданные в коде, используются внутри FXML-описания формы.
Загрузка FXML-формы при старте приложения вызывается примерно так:
Parent root = FXMLLoader.load(getClass().getResource("Sample.fxml"));
stage.setScene(new Scene(root));
stage.show();
Каких-то преимуществ подобное создание GUI не даёт. Визуального редактора нет, а править руками одинаково затратно как Java-код, так и FXML-описание.
Визуальный редактор
Форморисовалка есть в Visual Studio для VB и C#, в Adobe Flex, в Oracle JBuilder есть прекрасный редактор для Swing. Для JavaFX визульный редактор был объявлен ещё 2 года назад. Можно даже видео с ним посмотреть на странице http://www.flickr.com/photos/douglasbullard/3609213630/in/photostream/.
Но пока публичного релиза не было и неизвестно когда будет.
Ложка мёда в бочке дёгтя
Общая оценка скорей всего неудовлетворительная. Демо-приложения тормозят, внешний вид компонентов уступает Macintosh Aqua, Adone Flex или Microsoft Metro. Первая версия JavaFX появилась ещё в далёком 2008 году но Sun так и не смог довести технологию до ума.
Тем не менее, на последней JavaOne о JavaFX говорилось очень много. Будем надеяться что Oracle железной рукой направит разработчиков в нужное русло и заставит выдать наконец-то рабочий инструмент весто обещаний.