Журнал LinuxFormat - перейти на главную

LXF120:JavaFX

Материал из Linuxformat
Перейти к: навигация, поиск
JavaFX Создавайте продвинутые интернет-приложения (и не только) без лишних усилий

Содержание

JavaFX: Добавим красок

JavaFX
Часть 2: На одном только языке далеко не уедешь. Антон Черноусов познакомит вас с объектами, из которых строятся настоящие приложения с графическим интерфейсом.

На предыдущем уроке мы подробно рассмотрели базовые механизмы языка сценариев JavaFX Script, а сегодня сосредоточимся на возможностях JavaFX в области создания графического интерфейса пользователя. После прочтения этой статьи вы разберетесь с объектами-примитивами и применением эффектов, а также, в заключение, узнаете про обработку событий, генерируемых пользователем.

Мы не будем приводить полные исходные тексты учебных примеров, ограничившись лишь интересующими нас частями. Как и в прошлый раз, вы сможете найти все обсуждаемые программы на LFXDVD: советую вам прямо сейчас распаковать архив с диска, чтобы было удобнее следить за мыслью. Готовы? Тогда приступим.

Stage — основа GUI

Главный объект, с которого начинается создание пользовательского интерфейса – это Stage. Для работы с ним в вашем сценарии JavaFX Script необходимо подключить библиотеку javafx.stage с помощью ключевого слова import сразу после объявления пакета – например, так:

 package ru.golodnyj.lxf.fx;
 import javafx.stage.*;

Вы можете подключить как весь пакет с помощью символа *, так и отдельные классы – указанием их канонического имени, скажем, javafx.stage.Stage. Следующий простой сценарий (файл FirstStage.fx в примерах на диске) создает пустое окно приложения и выводит его в конкретную позицию на экране:

LXF120 76 1.jpg Рис. 1. Работа со свойством opacity у объекта Stage.

 Stage {
        title:This is Stage”
        x : 100 // Start point to Stage
        y : 200
        width: 300 // The width and height
        height: 400
 }

В этом листинге при создании объекта Stage устанавливается заголовок title, позиции по горизонтали и вертикали x, y, а также ширина и высота width, height.

Однако при таком задании параметров главного окна программы будет невозможно обратиться к его свойствам во время выполнения приложения. Для решения этой проблемы достаточно присвоить объект Stage некой переменной, как, например, это сделано в сценарии OpacityStage.fx:

 var s : Stage = Stage {...}

API объекта Stage достаточно скуден по своим возможностям, но, внимательно изучив его (документацию на английском языке можно найти по адресу http://java.sun.com/javafx/1/docs/api), легко обнаружить замечательное свойство opacity, которое варьируется в пределах от 0.0 до 1.0 и задает прозрачность окна. Например, значение opacity, равное 0.5, создает приятный полупрозрачный эффект, который можно видеть на рис. 1. К сожалению, возможности загрузить API для локального просмотра нет, и мне кажется, что с точки зрения Java-разработчика новый способ представления документации значительно уступает проверенному временем JavaDoc.

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

Графические примитивы

Безусловно, само по себе пустое окно никому не интересно. Фактически, все компоненты пользовательского интерфейса в JavaFX представляют из себя «узлы» – Node, то есть являются некоторым расширением класса javafx.scene.Node. Существует несколько типов узлов:

  • примитивы;
  • текст;
  • изображения;
  • медиа-контент;
  • Swing-компоненты.

Узлы размещаются в корневой области, которая называется «сценой» и представлена объектом Scene. Объект Scene содержит переменную content, в которую и помещаются узлы, как, например, в сценарии FirstScene.fx:

LXF120 77 1.jpg Рис. 2. Различные типы узлов, созданные нами в сценарии FirstScene.fx.

 var scane1 : Scene = Scene {
            content: [a, b, c]
             }
 var s : Stage = Stage {
        scene: scane1
        … }
 function run(){
          println(“Start the App”);
          s.visible = true; // make the Stage visible
          s.toFront();
 }

Результат работы программы можно видеть на рис. 2. В FirstScene.fx создаются три графических объекта a, b и c: это прямоугольник (Rectangle), окружность (Circle) и дуга (Arc). Все три наших объекта унаследованы от Node и являются графическими примитивами. Для работы с ними необходимо подключить пакет javafx.scene.shape.*;.

Пакет shape содержит всевозможные графические примитивы, каждый из которых имеет очень богатый API. Например, если мы рассмотрим уже созданный нами объект Arc, то среди его атрибутов можно найти поле type, которое определяет внешний вид примитива и может принимать три различных значения:

  • ArcType.ROUND – окружность с центральным углом как на рисунке 2 (по-моему, здесь есть что-то знакомое... да это же Пэкмен!);
  • ArcType.CHORD – вместо «скушанного» сектора будет хорда;
  • ArcType.OPEN – выглядит как ArcType.CHORD, но без линии хорды, соединяющей края центрального угла.

Конечно, создавать отдельные фигуры хорошо, но гораздо удобнее использовать их в совокупности и управлять ими как группой элементов: в JavaFX предусмотрен и такой сценарий. Существует специальный объект Group, который является узлом и позволяет хранить в себе другие объекты Node. Group предоставляет специальный атрибут – последовательность content, предназначенный, как и у Scene, для хранения Node-объектов.

LXF120 77 2.jpg Рис. 3. Наша «почти кнопка» на самом деле собрана из двух примитиво

В качестве примера рассмотрим создание несложной картинки, представленной на рис. 3. Для отрисовки такого изображения необходимо два элемента: это прямоугольник с закругленными краями (Rectangle) и текст (Text). Несколько забегая вперед, отметим, что текст выводится с помощью объекта Text, который также является наследником Node. Как видно из приведенного ниже кода FirstGroup.fx, Node-объекты перечисляются через запятую, то есть заносятся в последовательность content, а доступ к ним можно получить через переменную d.

 var d: Group = Group {
      content: [
        Rectangle {
           x: 30; y: 15; width: 150; height: 20;
           arcWidth: 20; arcHeight: 20; stroke: Color.GRAY;
           fill: LinearGradient {
               startX: 0.0, startY: 0.0, endX: 0.0, endY: 1.0, proportional: true
               stops: [
                   Stop {offset: 0.0 color: Color.WHITE},
                   Stop {offset: 1.0 color: Color.GRAY}
               ]}},
       Text {}]}

Градиенты

Наибольший интерес в приведенном выше фрагменте представляет свойство fill (заливка), а точнее, использованный для нее объект LinearGradient, который (кто бы мог подумать?) представляет собой линейный градиент. Переменные объекта LinearGradient: startX, startY, endX и endY определяют координаты начальной и конечной точек градиента, и таким образом задают его направление и размер охватываемой им области. Градиент можно размещать в любом направлении.

Хитрая переменная proportional при установке ее значения в true масштабирует переменные startX, startY, endX и endY относительно объекта, на который накладывается градиент (при этом значения координат должны находиться в диапазоне от 0,0 до 1,0). При установке proportional в false величины startX, startY, endX и endY имеют смысл абсолютных значений в пикселях.

Последовательность stops – это совокупность объектов Stop (опорных точек), задающих распределение цветов вдоль градиента. Таких точек может быть больше двух. Поле offset объекта top определяет точку, где градиент будет иметь некий заданный цвет, как число в диапазоне от 0,0 до 1,0 (то есть в долях от протяженности градиента). Цвет точек градиента определяется значением атрибута color. Кроме предопределенных цветов, можно задать свой оттенок в стандартной шестнадцатеричной нотации – это делается с помощью метода web объекта Color, как в примере ниже:

LXF120 78 1.jpg Рис. 4. Варианты радиальной заливки: без повторения (слева), стандартная периодическая (справа) и зеркальная (на переднем плане).

 stops: [
   Stop {offset: 0.0 color: Color.WHITE},
   Stop {offset: 0.5 color: Color.DARKBLUE},
   Stop {offset: 1.0 color: Color.web(«#ffffff»)}
 ]

Фактически существует три вида градиентов: Solid (сплошная заливка одним цветом), LinearGradient (линейный) и RadialGradient (радиальный). У последних двух типов есть возможность указать периодичность заливки с помощью свойства cycleMethod: без повторения (CycleMethod.NO_CYCLE), прямой цикл градиента (CycleMethod.REPEAT), прямой-обратный (CycleMethod.REFLECT). Какой смысл скрывается за этими значениями, можно видеть на рис. 4.

Работа с текстом

В целом, графических возможностей JavaFX с лихвой хватает для реализации любого способа представления информации, но вернемся к отображению текста. Как уже было отмечено ранее, Text – это объект типа Node, что позволяет работать с ним так же, как и с другими графическими объектами. Однако работу с его содержимым (то есть собственно текстом – буквами, знаками препинания и так далее) иногда следует отделять от отображения, что демонстрируется в сценарии TextEffect.fx и на рис. 5 (определение графа любезно предоставлено Википедией: http://ru.wikipedia.org):

 var text = «В математической теории графов и информатике\n граф –»;
 Stage {
    title: “TextEffect.fx” width: 200 height: 230 visible: true
    scene: Scene{
      fill: Color.WHITE
       content:[
          VBox{ spacing: 10 content:[
             Text{y: 35 x: 10 content: “Граф” font: Font{size: 30}},
             Text{y: 15 x: 10 content: text font: Font{oblique: true}},
             Text{y: 5 x: 30 content:
                “это совокупность объектов со связями между ними.” fill: Color.GREEN},
             ]}
          ]}
 }

LXF120 78 2.jpg Рис. 5. Расшифровка терминов средствами JavaFX выполняется не хуже, чем в настоящем электронном словаре

Основными атрибутами для объекта Text являются его положение x, y и содержание content. С помощью атрибута font можно в значительной степени повлиять на внешний вид текста. Объект Font определяет характеристики надписи: размер шрифта size, начертание oblique (наклонное), цвет заливки fill, имя гарнитуры name и так далее.

Эффектная трансформация

Помимо прочего, графические объекты JavaFX поддерживают самые различные эффекты и преобразования (трансформации). Что скрывается за этими словами? Ответ на этот вопрос понятен любому, кто работал с графическими редакторами, такими как GIMP или Adobe Photoshop. Эффект – это визуальное изменение, которое строится на базе текущего представления объекта на сцене. Для задания эффекта у объектов типа Node существует специальный атрибут effect.

Прежде чем использовать эффекты, необходимо подключить пакет javafx.scene.effect. Классическим эффектом является отбрасываемая от объекта тень, словно он является трехмерным и действительно может заслонять собой падающий свет. Тень может быть реализована с помощью объекта DropShadow или InnerShadow. Например, если вы внимательно просматривали исходные тексты сценария FirstGroup.fx, упоминавшегося нами ранее, то могли заметить внутри объекта Group пару закомментированных строк:

  effect: DropShadow{offsetX:5 offsetY:5 color: Color.DARKGRAY}
  effect: InnerShadow{offsetX:5 offsetY:5 color: Color.DARKGRAY}
  effect: Blend{
  topInput: DropShadow {
            offsetX: 4 offsetY: 4 radius: 6
            color: Color.DARKGRAY}
  bottomInput: DropShadow {
            offsetX: -4 offsetY: 4 radius: 6
            color: Color.DARKGRAY}
  }

Первая строка накладывает на объект Group эффект отбрасываемой наружу тени, в основе которой лежит цвет Color.DARKGRAY (темно-серый). Если оставить только вторую строку, то с помощью объекта InnerShadow будет создана тень, отбрасываемая внутрь объекта – иллюзия вдавленной под поверхность кнопки. Механизм эффектов реализован очень просто, и JavaFX даже позволяет комбинировать несколько эффектов – как, например, в последнем случае с Blend. Визуальный эффект от него интереснее, чем от двух предыдущих – скомпилируйте и запустите скрипт FirstGroup.fx, предварительно раскомментировав соответствующие строки.

Эффекты не ограничены только работой с тенями. Есть, например, любопытный эффект Reflection, который позволяет создать отражение (ну не могла же Sun Microsystems обойтись без него в JavaFX, ведь этот эффект у всех ассоциируется с Web 2.0!). Можно сделать небезосновательное предположение, что число доступных эффектов в следующих версиях JavaFX будет увеличиваться.

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

  • перенос (Translate);
  • вращение (Rotate);
  • масштабирование (Scaling) – пропорциональное изменение размеров;
  • деформация (Shear) – эффект от применения похож на сдвиг рисунка по осям – например, наклон, как в наклонном тексте.

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

События

Если вернуться к нашей «кнопке», то сразу станет понятна ее неполноценность. Для создания настоящего элемента управления необходимо реализовать обработку событий. На мой взгляд, по сравнению с объектами Swing в Java, сделать это в JavaFX значительно проще. У объектов Node заранее определено более десятка всевозможных событий, которые обрабатываются в том случае, если написана соответствующая функция.

Для примера рассмотрим скрипт FirstGroup2.fx, который является небольшой модификацией FirstGroup.fx. Разница заключается в том, что объект Group содержит следующий дополнительный код:

 effect: DropShadow{offsetX:5 offsetY:5 color: Color.DARKGRAY}
 onMousePressed: function( e: MouseEvent ):Void {
      e.node.effect = InnerShadow{offsetX:5 offsetY:5 color: Color.DARKGRAY}
 }
 onMouseReleased: function( e: MouseEvent ):Void {
      e.node.effect = DropShadow{offsetX:5 offsetY:5 color: Color.DARKGRAY}
 }
 onMouseClicked: function( e: MouseEvent ):Void {
      numOfClick++;
 }

Кроме того, в теле скрипта определены еще две переменные:

  var numOfClick = 0;
  var a : Text = Text {
      content: bind numOfClick.toString();
      x: 30;
      y: 80;
  }

Фактически, для нашей кнопки назначен эффект падающей тени и определены функции для обработки трех событий: нажатие клавиши мыши (onMousePressed – меняет эффект с тени, падающей наружу, на падающую вовнутрь), отпускание клавиши мыши (onMouseReleased – возвращает все как было) и обработка клика (onMouseClicked – увеличивает значение переменной numOfClick на единицу). Переменная a отображает число щелчков, которое было сделано мышью по кнопке. Обратите внимание на связывание (конструкция bind) – мы говорили о нем в LXF119.

И напоследок…

На данном уроке мы познакомились с некоторыми возможностями JavaFX по части пользовательского интерфейса: создали графический объект и реализовали обработку событий для него. Этого вполне достаточно для несложных приложений, но в более серьезных случаях бывает необходимо применять компоненты Swing и Java-классы. Я решил оставить этот вопрос вам на самостоятельное изучение: в конце концов, если вы уже знаете Swing или Apache POI, то разобраться с тем, как вызвать их из JavaFX Script, не составит для вас труда. Основа заложена – дополнительную информацию можно почерпнуть из документации и других ресурсов, перечисленных в прошлом номере. Если ваша программа выиграет приз в JavaFX Galaxy, дайте нам знать!

Онлайн-магазины

Оглушительный успех iTunes App Store как магазина приложений заставил крупных поставщиков взглянуть на это направление как на новую возможность распространения своих продуктов и удержанияНа конференции JavaOne, проходившей с 1 по 5 июня в Сан-Франциско (США), технологии JavaFX уделялось повышенное внимание. Среди участников конференции у нас имелся свой агент – Денис Магда, Sun Campus Ambassador из города Благовещенска Амурской области. Мы с радостью предоставляем вам его отчет о мероприятии. Linux Format (LXF): Денис, скажите, как простому студенту удалось побывать на JavaOne 2009? Кого для этого нужно убить? Денис Магда (ДМ): Убивать никого не пришлось [смеется]. Все дело в том, что мое увлечение технологиями Sun и реализация небольшого приспособления с использованием SunSPOT, Java и JavaFX заинтересовало боссов Sun Microsystems. LXF: Вы имеете в виду, сенсорно... выговорить не могу? ДМ: Да, да. Сенсорно- моторный интерфейс управления, по сути – это перчатки с кнопками и контроллерами SunSPOT. SunSPOT’ы позволяют определить изменение положений рук с помощью встроенных датчиков (акселерометров) и обеспечить беспроводную передачу данных на ПК. Кстати, управление контроллером осуществляется с помощью программы, написанной на Java, и приложение, принимающее данные на стороне ПК, тоже написано на Java. Весь код доступен по лицензии GPL на сейте проекта https://sensormotor-gloves.dev.java.net/. Там же можно посмотреть видеодемонстрацию. LXF: А каким образом используется в вашем проекте JavaFX? ДМ: О, я думал, как сделать красочную демонстрацию своего устройства, и написал демо на JavaFX. На сцене размещены несколько объектов с мультимедийным содержанием (картинки и видео), и с помощью перчаток можно выполнять различные операции: запускать ролики, увеличивать или уменьшать объекты, вращать их и так далее. Но для JavaOne пришлось создать гораздо более интересную демонстрацию. LXF: Отлично. И, конечно, ее исходные тексты тоже можно загрузить с сайта проекта? ДМ: Нет, боюсь, их там пока нет, но как только я освобожусь, думаю, выложу обе «демки »: и старую, и новую. Пока нет и официального видео с JavaOne, но можно посмотреть любительские съемки, например, здесь: http://www.youtube. com/watch?v=QKkHjSO_cAo. Вообще, JavaFX на JavaOne было уделено огромное внимание и среди стендов, и среди выступающих. В числе новинок – релиз JavaFX 1.2 и специальная среда разработки, причем это не NetBeans, и еще многое, о чем просто нельзя рассказать – это надо видеть. LXF: Читателей нашего журнала волнует такой вопрос: когда же будет версия JavaFX под Linux? ДМ: Скажу коротко, я ее уже видел... и вы тоже можете. Просто зайдите по адресу http://javafx. com/downloads/all.jsp: отсюда можно загрузить JavaFX 1.2 для Linux, Solaris, Mac OS X и Windows. LXF: Спасибо вам, Денис, за уделенное время и приятные новости! ДМ: И вам тоже спасибо клиентов.

Еще в мае был открыт магазин приложений Ovi (https://store.ovi.com/), разработанный Nokia. Доступ к ресурсу осуществляется прямо с мобильных телефонов Nokia. Так же, как и iTunes Store, сервис от финской компании позволяет загружать приложения, игры, видеоролики, подкасты.

Отметим, что сервис Ovi был русифицирован и стал доступен российским пользователям без задержек, а наиболее активные владельцы телефонов Nokia уже попробовали его в действии.

Незадолго до открытия сервиса Ovi Джонатан Шварц [Jonathan Schwartz], исполнительный директор компании Sun Microsystems, анонсировал запуск Java App Store: видеообращение по этому поводу можно посмотреть в официальном блоге http://blogs.sun.com/jonathan/entry/will_java_be_the_world. Сервис будет предоставлять возможность распространения ПО, написанного с помощью Java и JavaFX, как для мобильной платформы, так и для обыкновенных ПК. Официальное открытие магазина состоялось на конференции JavaOne 2009.

SunSPOT и JavaFX

На конференции JavaOne, проходившей с 1 по 5 июня в Сан-Франциско (США), технологии JavaFX уделялось повышенное внимание. Среди участников конференции у нас имелся свой агент – Денис Магда, Sun Campus Ambassador из города Благовещенска Амурской области. Мы с радостью предоставляем вам его отчет о мероприятии.

Linux Format (LXF): Денис, скажите, как простому студенту удалось побывать на JavaOne 2009? Кого для этого нужно убить?

Денис Магда (ДМ): Убивать никого не пришлось [смеется]. Все дело в том, что мое увлечение технологиями Sun и реализация небольшого приспособления с использованием SunSPOT, Java и JavaFX заинтересовало боссов Sun Microsystems.

LXF: Вы имеете в виду, сенсорно... выговорить не могу?

ДМ: Да, да. Сенсорно-моторный интерфейс управления, по сути – это перчатки с кнопками и контроллерами SunSPOT. SunSPOT’ы позволяют определить изменение положений рук с помощью встроенных датчиков (акселерометров) и обеспечить беспроводную передачу данных на ПК. Кстати, управление контроллером осуществляется с помощью программы, написанной на Java, и приложение, принимающее данные на стороне ПК, тоже написано на Java. Весь код доступен по лицензии GPL на сейте проекта https://sensormotor-gloves.dev.java.net/. Там же можно посмотреть видеодемонстрацию.

LXF: А каким образом используется в вашем проекте JavaFX?

ДМ: О, я думал, как сделать красочную демонстрацию своего устройства, и написал демо на JavaFX. На сцене размещены несколько объектов с мультимедийным содержанием (картинки и видео), и с помощью перчаток можно выполнять различные операции: запускать ролики, увеличивать или уменьшать объекты, вращать их и так далее. Но для JavaOne пришлось создать гораздо более интересную демонстрацию.

LXF: Отлично. И, конечно, ее исходные тексты тоже можно загрузить с сайта проекта?

ДМ: Нет, боюсь, их там пока нет, но как только я освобожусь, думаю, выложу обе «демки»: и старую, и новую. Пока нет и официального видео с JavaOne, но можно посмотреть любительские съемки, например, здесь: http://www.youtube.com/watch?v=QKkHjSO_cAo. Вообще, JavaFX на JavaOne было уделено огромное внимание и среди стендов, и среди выступающих. В числе новинок – релиз JavaFX 1.2 и специальная среда разработки, причем это не NetBeans, и еще многое, о чем просто нельзя рассказать – это надо видеть.

LXF: Читателей нашего журнала волнует такой вопрос: когда же будет версия JavaFX под Linux?

ДМ: Скажу коротко, я ее уже видел... и вы тоже можете. Просто зайдите по адресу http://javafx.com/downloads/all.jsp: отсюда можно загрузить JavaFX 1.2 для Linux, Solaris, Mac OS X и Windows.

LXF: Спасибо вам, Денис, за уделенное время и приятные новости!

ДМ: И вам тоже спасибо LXF

Персональные инструменты
купить
подписаться
Яндекс.Метрика