Фон в Andoid приложении

Все-таки, дизайн – дело важное, к тому же в мобильных приложениях, где конкуренция крайне велика. И начинать приходится с малого. Буковки там, кнопочки и фон приложения. Собственно про фон я сейчас и расскажу.
Сделать фон черным или зеленым не сложно. Достаточно указать цвет xml файле нужного intent:

<TableLayout android:background="#000000" />

Теперь задачка посложнее – сделать фоновый рисунок. Ну не сильно посложнее, если быть честным. Первое что мы делаем – это указываем откуда брать информацию по рисунку:

<TableLayout android:background="@drawable/background" />

Теперь создаем в папке res новую папку с названием drawable, а в ней файл background.xml, который наполняем такими данными:

<bitmap xmlns:android=http://schemas.android.com/apk/res/android android:src="@drawable/backgroundpicture" />

Главное не забыть положить в папку drawable само изображение и обозвать его backgroundpicture.png.
Запускаем эмулятор и видим, что получили мы именно то, что хотели.
А теперь представим, что хотим мы не одну большую картинку положить, а размножить маленькую. Замостить, так сказать. Ну вот сейчас то как раз и начнется… ничего. Просто немного изменяем background.xml файл:

<bitmap xmlns:android=http://schemas.android.com/apk/res/android android:src="@drawable/backgroundpicture" android:tileMode="repeat" />

Вот и все. Теперь наша маленькая картинка, повторенная бесконечное число раз создает фон программы. Не правда ли все элементарно?
Ну и чтоб всем стало совсем все понятно скажу – в LinearLayout добавлять android:background нужно в том случае если вы хотите статически замощённый фон, а в

<ScrollView><TableLayout android:background="@drawable/repeatline" / ></ScrollView> 

чтоб фон скролился вместе с текстом в программе.

Парсим json с помощью json-simple

Потребовалось мне недавно распарсить небольшой JSON, взятый со стороннего сайта. Естественно java и естественно не хотелось заморачиваться больше необходимого. И я пошел в интернеты искать что-то, что устроит меня по обоим этим параметрам. Первая строчка при поиске через Google – json-simple. Чтобы не противоречить самому себе и не усложнять задачу берем его и подключаем к проекту.
В кратком виде документ, получаемый мной от сервера выглядит так:

{
 "current_observation": {
  "weather":"Partly Cloudy",
  "temp_c":14,
  "relative_humidity":"72%",
 }
}.

Все просто и понятно.
Корнем всех добр json-simple является класс JSONParser, являющийся, как не трудно догадаться, парсером JSON документа.

JSONParser jsonParser = new JSONParser();

Теперь парсим JSON методом parse (оригинально, не правда ли?) и сохраняем его в json-simple объект JSONObject.

JSONObject jsonObject = (JSONObject)jsonParser.parse(здесь_ваш_json);

Ищем вхождение current_observation

JSONObject jsonObserv = (JSONObject)jsonObject.get("current_observation");

и получаем такой же объект но только не для корня JSON, а уже для него.
Ну, а далее все тем же методом get() получаем значения ключей:

Double temperature = Double.parseDouble((jsonObserv.get("temp_c").toString()));
String weatherType = jsonObserv.get("weather").toString();
Integer humidity = Integer.parseInt(jsonObserv.get("relative_humidity").toString().replace("%", ""));

Вот, собственно, и все.
Конечно, это был самый простой способ парсинга. Можно было делать это через Map’ы с итераторами, но, как вы помните, я искал именно простоты и удобства на неизменяемых по структуре документах.
Если захочется посмотреть на примеры, то их есть у гугла.
Пользуйтесь на здоровье.

Установка Oracle XE 11g на Ubuntu под VirtualBox

Вчера половину дня потратил на то, чтобы запустить СУБД Oracle XE 11g на Ubuntu в VirtualBox. Тысячи нервных клеток головного мозга были уничтожены, но задача, наконец, выполнена. И чтобы с этим смогли справиться люди, не имеющие в багаже английского языка я решил написать в этот блог кратенькую инструкцию.
Итак:
Что нам понадобится
VirtualBox – http://www.virtualbox.org/wiki/Downloads
Ubuntu – http://www.ubuntu.com/download/ubuntu/download (берем x64, так как только для нее есть Express версия Oracle)
Oracle Database Express Edition 11g Release 2 – http://www.oracle.com/technetwork/database/express-edition/downloads/index.html
Oracle SQL Developer – http://www.oracle.com/technetwork/developer-tools/sql-developer/downloads/index.html (не хотим же мы постоянно работать с SQL строками. GUI сильно упрощает жизнь) Читать далее

Стар(та)пер

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

Я говорю о книге Гая Кавасаки – Стартап. 11 мастер-классов от экс-евангелиста Apple и самого дерзкого венчурного капиталиста Кремниевой долины.

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

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

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

Пересказывать все то, что вы почерпнете из этого небольшого томика я не буду, да и не смогу – не тот жанр, но могу сказать, что если вы мечтаете стать владельцем собственной (скорее, высокотехнологичной) фирмы – вы обязаны прочитать книгу. Не потому, что ВСЕ что тут написано вам ОБЯЗАТЕЛЬНО пригодится; совершенно не обязательно (мы, как минимум, живем в условиях совсем другой страны и общества), но скорее, потому, что это – бизнес-биография человека, верящего в принцип «возмездия» за все хорошее и при этом добившегося немалого успеха обязательно подтолкнет вас к верным шагам в будущем.

OhYeah!

Недавно написал новую программу под Android, про которую не мог сказать здесь, так как в то время narsereg.ru лежал в дауне, а потом, как-то руки не доходили. И вот появилось немного времени и энтузиазма для написания небольшого поста.

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

Все очень просто – никаких заморочек. Запускаете программу -> Выбираете контакт -> Вводите тему для разговора -> Сохраняете. При начале разговора с нужным абонентом получаете сообщение на экране.

Программа называется OhYeah!, как вскрик, когда англоязычанин вспоминает о чем-то – аналог российского АхДа! А вот и ссыль на нее – https://market.android.com/details?id=com.narsereg.ohyeah

А для любителей QR:

Pragmatic Unit Testing in Java with JUnit

Только что закончил чтение книги Pragmatic Unit Testing in Java with JUnit Эндрю Ханта и Дэвида Томаса.

Давно пора было немного систематизировать знания по тестированию, чем я, собственно, и занялся. То, что до этого хранилось у меня в голове по тестированию было, порой, странно и запутано. И, несмотря на всю элементарность работы с JUnit, редко применялось в достаточных количествах и в нужных местах. Со времен посмотрю, изменится ли что-нибудь. Надеюсь, что да.

Теперь перейдем к самой книге.

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

Собственно JUnit в книге посвящено не так чтобы много места. По большей части это все-таки книга по основам тестирования. И это, пожалуй, минус. Ну что им стоило больше времени потратить на обучение конкретно JUnit? Просто когда ты берешь в руки книгу на обложке которой красуются слова JUnit и Java, то именно на них ты и ориентируешься, так как они вынесены в заголовок.

То есть, книга то отличная, хорошо написанная, но не про то, на что мы все рассчитывали.

Про теорию тестирования, подающуюся в Pragmatic Unit Testing in Java with JUnit никаких ругательных слов я сказать не могу. Эта часть описана более, чем полностью и в терминах, усваивающихся великолепно. После прочтения вы поймете как, что, где и почему нужно тестировать (а тестировать нужно абсолютно все, везде, всегда и всеми возможными способами).

В сухом остатке: книга отличная, но слишком мало отведено теме конкретной реализации тестирования. Читайте Pragmatic Unit Testing + javadocs и будет вам счастье.

Будущее JavaFX. Часть 2

Как и было обещано продолжаю. Что же нас ждет в свежем 2.0 релизе JavaFX кроме смены парадигмы разработки?

Так как последовательности в JavaFX неизменяемы и не поддерживают null-значения, то требовались некоторые изменения. Мы их и получим. Обещаны ObservableList и ObservableMap.

Поддержка многопоточности станет более полной и удобной (например, исчезнет необходимость в классе JavaTaskBase). Кроме того, появится возможность запускать процесс создания сцены в другом потоке, а затем объединять его с основным.

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

Улучшиться как скорость работы работы приложения, так и скорость его загрузки. Кроме того с меньшими затратами будет работать и анимация.

Наконец-то мы получим новый движок рендеринга Prism, который будет поддерживать как DirectX, так и OpenGL. Кроме того будет возможность программного рендеринга. Появится компонент, позволяющий изменить способ рендеринга на Prism с AWT.

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

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

Наконец, в стандартные компоненты придет TableView. Ждали мы этого долго и наконец дождались. Еще появятся SplitView, TabView. MediaPlayer позволит сразу приступать к работе с медиа, так на этом компоненте уже будут все необходимые элементы управления.

С интернетом тоже будет бОльшая интеграция. Появится компонент WebView, отображающий web страницу, а также WebBrowsr (сразу готовый к серфингу браузер).

Ну вот, в принципе, и все. Нововведений много, а взлетит ли это все или нет – узнаем уже в следующем году.

Будущее JavaFX. Часть 1

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

Я, конечно же, говорю об отказе от языка JavaFX Script. В чем была необходимость этого события я понять не в силах, но несмотря на все наши причитания во 2-й версии JavaFX, столь полюбившегося нам синтаксиса мы уже не увидим. Естественно, уже появился fork (который получил название Visage), но все же без такого могущественного союзника как Oracle (или если не получит поддержки, например, Apache) конкурировать на рынке он, к сожалению, не сможет.

Что же нам предлагает Oracle взамен? А предлагает она нам тоже самое, но под другим соусом. Мы увидим отличный продукт, но с синтаксисом классической Java. Разработчик получит GUI, но получать мы его будем не из скриптового языка, а из JavaBeans, содержащего все необходимые компоненты. То есть, богатство интерфейса JavaFX объединится с богатством самого языка Java. Во всяком случае, так обещается, а мы будем надеяться, что все не усложниться до того, что работать с этим будет невозможно.

В следующем посту посмотрим на JavaFX 2.0, так что далеко от мониторов не отходите.

Чистый кот


Довольно давно меня интересовал способ написания АДЕКВАТНОГО кода на любом языке программирования. Так уж получилось, что в течение длительного времени я занимался исключительно ухудшением своего программного почерка. Собственно писал так, как меня учили – лишь бы работало. Оно и работало. И даже проходило тесты, но возвращаться к коду было абсолютно невозможно – разобрать свой почерк без длительного вкуривания комментов (слава нулям и единицам – их я осиливал) я не мог. Несколько месяцев назад я полез в старый код, который писал еще на Delphi и ужаснулся тому, что понять ничего не возможно как не пытайся. В этот момент меня стукнуло по голове – надо браться за чистоту и понятность кода. Погуглив секунд 30 я понял, что лучшее, что написано на данный момент – «Чистый код» Роберта Мартиина. Так как в моей олимпийской столице найти хоть что-то отличное от книг по Delphi нереально, то заказал через интернет. Дождался. Прочитал. Читайте краткую рецензию.

Конечно, можно долго рассуждать про то, какой код можно читать лучшим – быстрый или читаемый (читаемый и быстрый – это идеал). Я свой выбор сделал. Нечитаемый код бесполезен, так как не подлежит копипасту. Копипаст – жесткий способ проверки кода. Если в двух проектах нужен примерно один функционал, то дважды писать плохой код – это намного хуже, чем скопировать хороший. Если же вернуться к книге, то она учит писать именно такой хороший код.

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

Еще мне очень понравилось, что Роберт Мартин написал все очень краткими главами, которые просто прочитать даже в те моменты, когда ты отвлекаешься от своего кода, чтобы поплевать в потолок и помечтать о собственном Гугле. Немного напрягла глава про последовательное очищение кода, написанная интересно, но включающая слишком большие куски кода, которые читать (а потом еще и сравнивать с новым релизом) крайне сложно. Уверен, что можно было бы сделать это и попроще. Хотя, что я могу знать.

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

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

А название этой записи мне навеяла другая книга этого издательства – «Как пасти котов». Кстати тоже довольно любопытная.

JavaFX для меломана. Часть 3

И вот, после трех месяцев мы, наконец-то, оказались на финишной прямой. Последний бой – он трудный самый.

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

Что осталось? Вот основные пункты:

1. Добавление файлов в список плейлиста.

2. Проигрывание этих файлов.

3. Перемотка по плейлисту.

4. Управление звуком.

5. Вывод названия трека на экран.

6. Перемотка внутри песни.

Так как времени мало, а материала много, то именно по этим пунктам и пройдемся.

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

Листинг 1.
onMouseClicked: function(evt: MouseEvent): Void {
  if ((evt.clickCount == 1) and (evt.button == MouseButton.PRIMARY))
  then {
    var dialogOpen : JFileChooser = new JFileChooser();
    dialogOpen.setMultiSelectionEnabled(true);
    dialogOpen.setFileFilter(new Mp3FileFilter());
    dialogOpen.setAcceptAllFileFilterUsed(false);
    if (JFileChooser.APPROVE_OPTION == dialogOpen.showOpenDialog(null)) {
      for (file in dialogOpen.getSelectedFiles()){
        insert file.getAbsolutePath() into fileList;
      }
    }
  }
}

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

Листинг 2.
class Mp3FileFilter extends FileFilter{
  override public function accept(file : File) : Boolean{
    if (file.getName().endsWith(".mp3"))
    then { return true; };
    if (file.isDirectory())
    then { return true; };
    return false;
  }
  override public function getDescription() : String{
    return "Mp3 files";
  }
}

И указываем, что этот фильтр необходимо использовать dialogOpen.setFileFilter(new Mp3FileFilter()). Все, теперь при запуске окна JFileChooser будут видны только папки и файлы с расширением mp3.

В рамках статьи нам понадобятся свойства setMultiSelectionEnabled(true), позволяющее выбирать несколько файлов одновременно, и setAcceptAllFileFilterUsed(false), убирающее возможность просмотра всех файлов (только mp3). Далее программа проверяет, была ли нажата кнопка Open, и если это так, в переменную fileList (а она, напомню, связана со списком песен) добавляются абсолютные пути выбранных файлов (file.getAbsolutePath()).

Вот теперь мы готовы к решительному шагу запуска медиафайла в проигрывателе. Будем это делать двойным кликом на файле в плейлисте, как это принято в больших плеерах. Для этого достаточно добавить пару строчек в код listviewPlaylist:

Листинг 3.
onMouseClicked: function(evt: MouseEvent): Void {
  if ((evt.clickCount == 2) and (evt.button == MouseButton.PRIMARY))
  then {
    playMedia(fileList[listviewPlaylist.selectedIndex]);
  }
}

Здесь вызывается функция playMedia(), которую рассмотрим чуть позже, так как она требует небольшой подготовки с нашей стороны. Добавить работоспособности интерфейсу можно назначив onMouseClicked для кнопок перемотки:

Листинг 4.
onMouseClicked: function(evt: MouseEvent): Void {
  if ((evt.clickCount == 1) and (evt.button == MouseButton.PRIMARY)) {
    if (listviewPlaylist.selectedIndex != sizeof listviewPlaylist.items - 1)
    then {
      listviewPlaylist.selectNextRow()
    } else {
      listviewPlaylist.selectFirstRow();
    }
    playMedia(fileList[listviewPlaylist.selectedIndex]);
  }
}

Здесь представлен код для кнопки Вперед и он прост как две копейки – при нажатии на кнопку проверяется условие на конец списка, в зависимости от результата выбирается следующий или первый трек и запускается все та же незнакомая функция playMedia(). Кнопка Назад аналогична по функциональности и ее код приводиться здесь не будет.

Следующим пунктом списка мы должны рассмотреть звук, а точнее его регулировку. Для этого на форму положим Swing-компонент Slider:

Листинг 5.
sliderVolume = Slider {
  layoutX: bind display.layoutX + 10
  layoutY: bind display.layoutY + 10
  min: 0
  max: 9
  value: 0
  vertical: true
  height: 80
}

Переменные layoutX и layoutY – положение слайдера на форме; min и max – минимальное и максимальное значение слайдера; value – значение по умолчанию; vertical – показывает, что слайдер имеет вертикальное расположение; height – высота в пикселах. Теперь привязка к громкости mediaPlayer будет выглядеть как одна строчка в переменных этого компонента:

volume: bind (9 - sliderVolume.value) / 10

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

Листинг 6.
trackName = Text {
  content: bind track;
  wrappingWidth: 130
  layoutX: bind display.layoutX + 30
  layoutY: bind (display.height - trackName.layoutBounds.height) / 2
    + display.layoutY + trackName.font.size / 2
  fill: Color.AQUA
  textAlignment: TextAlignment.CENTER
  font: Font{ size:14 }
  effect: Bloom{ }
}

Самая главная строчка здесь – content: bind track. С помощью нее выводимый текст привязывается к переменной track типа String.

Чтоб не загружать статью еще одним огромным листингом предлагаю открыть исходные коды программы и найти место, где мы выводим на сцену lineProgress и rectProgress. LineProgress – линия, по которой будет двигаться слайдер перемотки. Более интересен другой компонент – rectProgress, являющийся тем самым ползунком перемотки песни. Здесь мы используем переменную blocksMouse, которая запрещает передавать событие вниз по слоям интерфейса. Эту возможность необходимо использовать для того, что бы при перетаскивании ползунка не начинала двигаться наша форма (напомню, что мы добавили возможность drag’n'drop для Stage в прошлой статье). Листинг обработчика событий для этого компонента необходим, так что вот и он:

Листинг 7.
onMousePressed: function(e: MouseEvent):Void {
  timelineProgress.pause();
  beginPointX = e.sceneX - rectProgress.width / 2;
}
onMouseDragged: function(e: MouseEvent):Void {
  var minPosition = lineProgress.layoutX - rectProgress.width / 2;
  var maxPosition = lineProgress.layoutX - rectProgress.width / 2 + 350;
  var xPosition = e.sceneX - rectProgress.width / 2;
  if(xPosition <= minPosition)
  then {
    xPosition = minPosition
  } else if (xPosition >= maxPosition)
  then { xPosition = maxPosition }
  rectProgress.layoutX = xPosition;
}
onMouseReleased: function(e: MouseEvent):Void {
  resumeMedia(e.sceneX - rectProgress.width / 2
    - lineProgress.layoutX - rectProgress.width / 2);
}

В этом коде придется разобраться достаточно подробно. Во-первых – что такое timelineProgress?

Листинг 8.
var timelineProgress = Timeline {
  repeatCount: Timeline.INDEFINITE
  keyFrames : [
    KeyFrame {
      time : bind Duration.valueOf(mediaDurStep);
      canSkip : true
      action: function () {
        if (rectProgress.layoutX >= lineProgress.layoutX - rectProgress.width / 2 + 350)
        then { } else { rectProgress.layoutX++ }
      }
    }
  ]
}

TimelineProgress имеет тип TimeLine – один из базовых типов JavaFX, с которыми придется работать постоянно. TimeLine дает нам возможность изменения параметров нашего приложения в процессе выполнения приложения. Стоит рассмотреть его подробнее. Ключевые переменные этого типа следующие:

1. autoReverse – разрешает возврат анимации. После завершения анимации объект возвращается на исходную позицию по той же траектории.

2. keyFrames – содержит последовательность KeyFrame.

3. repeatCount – количество повторов TimeLine.

4. time – указывается с какого времени начать проигрывание анимации.

В нашем случае repeatCount получил значение Timeline.INDEFINITE. Это значит, что анимация будет повторяться бесконечное количество раз.

В переменной keyFrames мы используем только один компонент. KeyFrame – своеобразная единица анимации, которая выполняется необходимое количество раз с интервалом time. Action – функция, которая выполняется каждый период времени. Наша функция перемещает слайдер перемотки по линии и нельзя допустить, чтоб он вышел за пределы этой полосы перемотки, для этих целей и написана проверка на границы. Длина полосы перемотки – 350 пикселей.

TimeLine имеет четыре функции:

1. pause() – ставит анимацию на паузу, то есть временно ее приостанавливает.

2. play() – снимает анимацию с паузы, либо запускает с указанной позиции.

3. playFromStart() – запускает TimeLine с самого начала.

4. stop() – останавливается анимация и возвращает все значения в начальные позиции.

После всех этих строк теории становится немного понятнее практика. В Листинге 7 событие onMousePressed запоминает начальную позицию ползунка и останавливает анимацию. При перетаскивании вызывается onMouseDragged, в котором мы просто перемещаем ползунок по полосе перемотки. Опять же, постоянно следим за тем, что бы Rectangle не выходил за границы. И, наконец, при отпускании кнопки мыши вызываем resumeMedia() – функцию, которая продолжает выполнение timelineProgress и включает наш трек в выбранном месте. Делается это так:

Листинг 9.
function resumeMedia(position : Number){
  mediaplayer.mediaPlayer.currentTime = Duration.valueOf(position * mediaDurStep);
  timelineProgress.play();
}

Здесь position – положение слайдера на полосе перемотки. Duration.valueOf() переводит некоторое значение в тип данных Duration – время. В нашем контексте мы устанавливаем текущим временем внутри песни положение ползунка, умноженное на шаг выполнения TimeLine. После чего возобновляем выполнение timelineProgress().

Осталась малость – разобраться с нашим Неуловимым Джо – функцией playMedia(). Вот ее листинг:

Листинг 10.
function playMedia(mediaSrc : String){
  mediaplayer.mediaPlayer.stop();
  rectProgress.layoutX = lineProgress.layoutX - rectProgress.width / 2;
  playPause = true;
  mediaplayer.mediaPlayer.media = Media{source: "file:/{mediaSrc.replace("\\","/").replace(" ","%20")}"};
  mediaDurStep = mediaplayer.mediaPlayer.media.duration.toMillis() / 350;
  mediaplayer.mediaPlayer.play();
  timelineProgress.playFromStart();
  track = mediaSrc.substring(mediaSrc.lastIndexOf("\\") + 1);
}

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

1. Останавливается проигрывание предыдущей песни.

2. Слайдер перемотки устанавливается в начальное положение.

3. Переменная playPause (на нее, например, завязано переключение кнопки Пауза/Проигрывание) устанавливается в true.

4. Присваиваем переменной media новый медиафайл (здесь производится форматирование и приведение к принятому в JavaFX имени файла).

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

6. Запускаем проигрывание файла.

7. Запускаем наш TimeLine с начала.

8. Присваиваем переменной track (к ней привязано название песни, выводимое на экран) значение, которое будет выглядеть примерно как «название-песни.mp3″.

Ну, вот и все. Теперь наша программа готова к выполнению своих непосредственных задач. Компилируем код и проверяем.

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

Ну а исходники вы как всегда найдете по этой ссылке.