Вот и вышла в Мире ПК моя последняя статья серии про JavaFX. Но так как далеко не все читают этот журнал я решил напечатать ее и здесь. Читайте на здоровье.

Любой житель нашей планеты, за исключением редких папуасов, знаком с технологией под названием Java. И если вы не папуас, то наверняка пользовались телефоном с поддержкой Java-приложений, видели программу, написанную на Java, или хотя бы раз выходили в Интернет и сталкивались с Java-аплетом. Кто-то, может быть, даже добавит к перечисленному JavaScript, широко распространенный в Сети. И этот кто-то будет совершенно неправ, так как Java и JavaScript связаны разве что схожими названиями.

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

Главным минусом виртуальной машины Java на протяжении долгих лет являлось полное отсутствие адекватных библиотек для создания интерфейса. Хотя SWT и Swing и представляют собой мощнейшие системы отображения графического интерфейса, все же их никогда не назвали бы «шустрыми» и современными.

И вот, 4 декабря 2008 г. Sun Microsystems наконец-то выпустила то, что так долго ждали все любители красивого и удобного интерфейса, — язык JavaFX.

Представители корпорации Sun позиционируют свой продукт как RIA (Rich Internet Application), но JavaFX охватывает не только эту нишу. Не менее важна возможность интеграции нового интерфейса в уже написанное настольное приложение, процесс создания которого и рассмотрим в данной статье. В первой ее части будут приведены основы языка JavaFX, а синтаксис и конструкции мы обсудим в продолжении.

Для начала нужно выбрать среду разработки. Основной IDE для программистов, использующих JavaFX, является NetBeans, которую мы и станем применять. Дистрибутив ее находится на сайте http://www.netbeans.org. Во время написания статьи последняя стабильная версия данной среды была 6.7, и потому именно с ней мы и станем практиковаться. А чтобы не мудрствовать, скачайте с сайта сборку со встроенной поддержкой JavaFX.

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

Для начала разработаем интерфейс. Поскольку мы выбрали небольшой проект, то и интерфейс сделаем похожим на дешевые китайские MP3-плееры. По-моему, вполне правильное решение. Весь листинг первого урока можно скачать здесь. Значит, когда будете читать эту статью, откройте единственный (пока!) файл листинга под названием Main.fx и смотрите на него. Итак, приступим.

pic1

Запускаем установленную среду NetBeans и создаем новый JavaFX-проект. Естественно, мы серьезные люди и потому назовем проект ChinesePlayer, а главному файлу дадим имя com.pcworld.chineseplayer.Main. Вот в принципе и все. Мы готовы к свершениям, первым из которых станет решительное переименование заголовка приложения (title): с Application title на «Китаский плееир» (назовем по-русски — в знак гордости за свою страну, а ошибки — для аутентичности).Как выглядят дешевые китайские плееры за 1000 руб.? Правильно, небольшие продолговатые устройства с парой кнопок и маленьким монохромным экраном в центре. Такой мы сейчас и сделаем.

В основе всего интерфейса JavaFX лежит объект Stage, без его определения ничего не получится. Stage — это сама форма с кнопками сворачивания/разворачивания/закрытия окна. В параметрах данного объекта задаются размер окна и все его атрибуты. В нашем случае размер окна не имеет значения, так как в параметрах мы указываем стиль StageStyle.TRANSPARENT — сделать окно без рамки.

Вторым по важности элементом любой формы является сцена — Scene. Сцен в Stage может быть несколько, но тогда их необходимо менять. Мы же выбрали простой вариант без каких-либо изысков, а значит, будем использовать лишь одну сцену. В нашей сцене первым параметром стоит fill — он предназначен для определения цвета фона. Укажем значение fill: Color.TRANSPARENT, что сделает нашу форму не только не имеющей границ, но и прозрачной. А кому нужно абсолютно прозрачное окно без какой-либо смысловой нагрузки? Правильно, никому, и потому самое время наполнить сцену содержимым. Параметр content в JavaFX служит лишь для одного — он содержит внутри квадратных скобок все те элементы, которые должны быть объединены. В данном случае это будут компоненты на форме. Далее можно увидеть, как используется компонент Group, данный чуть выше в основном листинге на «Мир ПК-диске». Кстати, его объявление выглядит следующим образом: var player: Group = new Group(), где var — зарезервированное слово для объявления переменных, player — имя переменной, Group — тип данных, а все то, что идет после знака равенства, — присваиваемое значение. Кроме var, есть еще def, позволяющий создавать read-only-переменную, т.е. константу.

pic2

В JavaFX принято несколько логически связанных визуальных компонентов объединять в группу. В данном случае такой группой будет player с тем же параметром content, что был и при рассмотрении сцены. Внутри этой группы мы поместим несколько компонентов, позволяющих показать создаваемый плеер во всей красе. Рассмотрим их по очереди (листинг 1).

Листинг 1
case = Rectangle {
  x: 20, y: 20
  width: 450, height: 150
  fill: Color.rgb(5, 5, 5)
  arcHeight:150 arcWidth:80
  stroke:Color.DARKRED strokeWidth:15
  effect: Lighting {
    diffuseConstant:1.5
    light: DistantLight {
      azimuth: -135
    }
    surfaceScale: 1 specularConstant:0.1
  }
}

Объект Case — корпус нашего плеера. Как следует из объявления типа данных, это прямоугольник с размерами 400×150 пикселов почти черного цвета.

Цвет в JavaFX можно задавать несколькими способами. Вот основные из них:

Color.ЦВЕТ — значения, соответствующие нужному цвету, можно выбрать из списка автозаполнения кода, нажав комбинацию клавиш +Space;

Color.rgb(0, 0, 0) — в скобках указывается интенсивность красного, зеленого и синего оттенков;

Color.web(0xffffff) используется шестнадцатеричное представление цвета, принятое в Интернете. Также существуют и методы для градиентной заливки — LinearGradient и RadialGradient. Их мы применять не будем, а чтобы узнать о них более подробно, можно обратиться к справочной системе.

Значения arcWidth и arcHeight нужны для скругления углов прямоугольника. А вот параметры Stroke и strokeWidth описывают рамку плеера: первый задает цвет рамки, второй — ее ширину.

Теперь корпус готов. Осталось добавить немного спецэффектов с помощью параметра effects. Мы применим эффект освещения Lighting, чтобы объект стал реалистичнее. Уточним кое-какие его особенности: diffuseConstant обеспечивает рассеивание света, specularConstant придает объекту блеск, создавая эффект зеркала, surfaceScale делает объект по-настоящему трехмерным, реализуя эффект затемнения его краев. Наконец, параметр корпуса light позволяет указать, какого типа свет направлен на объект. В рассматриваемом примере используется равномерное освещение, источник которого находится сверху слева.

Перейдем к описанию экрана плеера, задаваемого в листинге 2 объектом display. Переменные, описывающие прямоугольник, вам уже знакомы. Уточним два новых параметра: layoutX и layoutY. Эти переменные — методы позиционирования узла на сцене. С их помощью мы разместим экран в центре корпуса плеера.

Листинг 2
display = Rectangle {
  width: 170, height: 100
  fill: Color.GREY
  layoutX: bind (case.width - display.layoutBounds.width) / 2 + case.y
  layoutY: bind (case.height - display.layoutBounds.height) / 2 + case.x
  effect: Lighting {
    diffuseConstant:0.5 light: DistantLight { azimuth: 135 }
    surfaceScale: 1 specularConstant:0.1
  }
}

Обратите внимание на слово bind — оно довольно быстро становится лучшим другом JavaFX-разработчика. Его основная задача заключается в том, чтобы связывать переменную с определенными событиями. Указав bind при присваивании переменной, вы «заставляете» ее следить за всеми переменными, участвующими в ее вычислении. Так, в нашем случае, если изменится ширина или положение корпуса, дисплей все равно окажется в его центре.

С прямоугольниками разобрались, но не одними же ими живет программист? Опишем для примера круг. Пусть это будет кнопка плеера (листинг 3)

Листинг 3
buttonPlay = Circle {
  radius: 50 fill: Color.DARKRED
  centerY: bind case.height / 2 + case.y
  centerX: bind display.layoutX - 70
  effect: Lighting {
    diffuseConstant:1.5
    light: DistantLight { azimuth: -135 }
    surfaceScale: 1 specularConstant:0.5
  }
}

Кратко рассмотрим все используемые переменные класса Circle, хотя их предназначение легко понять из названий. Например, radius — радиус круга. С параметрами fill и effect вы уже знакомы, а в переменных centerX и centerY хранятся координаты центра круга.

Треугольники на кнопках сделаны с помощью фигуры polyline, пример которой дан в листинге 4.

Листинг 4
polylinePlay = Polyline {
  points : [
    buttonPlay.centerX - 20,
    buttonPlay.centerY - 30,
    buttonPlay.centerX + 30,
    buttonPlay.centerY,
    buttonPlay.centerX - 20,
    buttonPlay.centerY + 30,
    buttonPlay.centerX - 20,
    buttonPlay.centerY - 30
  ]
  strokeWidth: 1.0 stroke: Color.WHITE
  visible: true fill:Color.WHITE
  effect: DropShadow { offsetY: 4 }
}

Класс Polyline позволяет рисовать любые фигуры из прямых линий, задавая координаты через запятую (x и y). Делается это внутри квадратных скобок переменной points. Параметр Visible сообщает о том, что фигура будет показана на экране (это необходимо для того, чтобы менять ее на два прямоугольника, символизирующих паузу), а эффект DropShadow показывает тень у фигуры и добавляет немного живости в картинку.

Осталось нарисовать только кнопки перемотки на следующий/предыдущий трек. Они представляют собой полукруг с тем же радиусом, что и у кнопки воспроизведения (листинг 5).

Листинг 5
buttonPrev = Arc {
  centerX: bind display.layoutX + display.width + 70,
  centerY: bind case.arcHeight / 2 + case.x
  radiusX: 50, radiusY: 50
  startAngle: 90, length: 180
  type: ArcType.CHORD
  fill: Color.GREEN
  effect: Lighting {
    diffuseConstant:1.5
    light: DistantLight { azimuth: -135 }
    surfaceScale: 1
  }
}

Переменные centerX и centerY вам уже известны, а вот параметр radius здесь превращается в два разных радиуса по ширине и высоте дуги соответственно — radiusX и radiusY. Значение startAngle задает начальный угол дуги, а length — длину арки в градусах. Переменная type содержит тип арки (в JavaFX их три — CHORD, ROUND и OPEN).

pic3

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