Программирование мобильных телефонов на Java

         

Модель работы мидлета



5.1.1. Модель работы мидлета



После успешной компиляции примера HelloMIDlet и запуска на любом понравившемся вам эмуляторе, на дисплее эмулятора в верхнем левом углу появится надпись HelloMIDlet. В нашем случае мидлет всего один, ни возможна ситуация когда будет несколько мидлетов, то есть MIDlet suite (набор мидлетов), тогда сервис телефона автоматически создаст меню выстроив все имеющиеся мидлеты друг под другом, предоставляя возможность в выборе программы. Но это не значит, что после того, как вы войдете в ваше приложение, сервис телефона и далее будет так же создавать за вас меню. Нет, действия по структуризации приложения, созданию списков и меню лежит на плечах программиста. На Рисунок 5.3 изображено Меню телефона с набором различных программ.

Для того чтобы запустить программу на эмуляторе, необходимо нажать кнопку Select (выбор), после чего вы попадаете непосредственно в рабочий цикл приложения. После нажатия клавиши Select, то есть подачи команды активизации приложения, в мидлете происходит поиск метода startApp(), который является начальной и входной точкой всех программ. И уже в методе startApp () идет обработка соответствующего программного кода и как следствие, выполнение работы приложения. Конечно, код находящийся до метода startApp (): объекты, конструктор и так далее, так же инициализируются, но активизация рабочего процесса мидлета происходит с вызовом метода startApp ().



Автоматически созданное меню



Рисунок 5.7. Автоматически созданное меню



Задав нужные команды для конкретного объекта Displayable, и создав код их обработки, вы получаете отличный механизм навигации. Но это не единственный способ перехода с экрана на экран. Каждый из четырех классов Form, List, TextBox и Alert имеет свои встроенные средства для создания списков, меню, таблиц, полей, загрузки изображений и так далее. При знакомстве с каждым из классов мы обязательно рассмотрим имеющиеся возможности. А пока давайте разберем механизм автоматического создания меню и обработки имеющихся команд.

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



Команда выхода из программы





Рисунок 5.2. Команда выхода из программы



Такая схема отображения различных команд реализована на всех без исключения мобильных телефонах. Единственное, что может изменяться- это способ отображения этих команд. У некоторых производителей мобильных телефонов команды располагаются под экранными клавишами, а у других, ряд команд формируется в виде меню.

Класс Command имеет два конструктора с тремя и четырьмя параметрами. В примере был использован конструктор из трех параметров, посмотрим, как выглядит прототип конструктора класса Command:

public Command( String label, int commandType, int priority )

Параметры конструктора класса Command:

 label - это переменная типа String, содержащая метку в виде простого текста. В примере использовалась команда Выход. Эта строка текста может находиться под кнопками дисплея, либо в виде элемента меню. Обычно команда - это короткое слово. Если необходимо использовать длинное слово, то нужно вызвать конструктор класса Command с четырьмя параметрами;  commandType - тип команды соответствующей выбранным действиям. Имеются команды BACK, CANCEL, EXIT, HELP, ITEM, SCREEN, STOP.  BACK - возврат к предыдущему экрану;  CANCEL - отмена произведенных действий;  EXIT - выход из приложения;  HELP - вызов справки;  ITEM - обычно используется для работы с классом Choice, и производит выбор элемента из группы элементов;  SCREEN - представление нового экрана;  STOP - остановка выполняемых действий.  priority - это приоритет, назначенный для данной команды относительно других команд, имеющихся на дисплее. Приоритет задается целым числом, где более низкое число указывает на более высокое значение.


За конструктором класса HelloMIDlet () следует ключевой метод основного класса мидлета startApp ().

public void startApp() { TextBox t=new TextBox("HelloMIDlet","Текст",256,0); t.addCommand(exitCommand); t.setCommandListener (this) ; mydisplay.setCurrent(t) ; }

Метод startApp() вводит приложение в активное состояние и является своего рода входной точкой для всей программы. В рассматриваемом примере для вывода текста на экран используется класс TextBox. Чтобы разобраться, как это происходит, необходимо рассмотреть конструктор класса TextBox:

public TextBox (String title, String text, int naxSize, int constraints)

Параметры конструктора класса TextBox:

 title - это титл или основное название, размещенное в верхней части дисплея;  text - текст, выводящийся непосредственно на экран. Текст, выводимый на экран можно редактировать и даже не выводить вовсе, выставив значение этого параметра в значение null;  maxSize - максимальное количество символов выводимого на экран текста;  constraints - с помощью этого параметра можно производить специальные ограничения, но пока рекомендую выставить параметр в 0.


То есть, создав объект класса TextBox, вы задаете область экрана, в которой существует свое название и количество выводимых символов. В следующих двух строках кода:

t.addCommand(exitCommand) ;  t.setCommandListener(this) ;

сначала добавляется команда Выход, к текущему экрану телефона представленному классом TextBox, а затем с помощью метода setCommandListener () устанавливается обработка событий для этой команды Выход, используя метод интерфейса GoimandListener . Самая последняя строка кода:

mydi splay. setCurrent (t);

отражает текущую информацию на экране. Этот метод подобен кнопке Обновить в Internet Explorer. Вызывая каждый раз метод setCurrent (), вы будете обновлять информацию на дисплее телефона. Следующий метод в примере:

public void pauseAppf)

Тело этого метода пока отсутствует, но с его помощью можно поместить мидлет в состояние паузы и освободить часть используемых ресурсов приложения. Дальше идет метод destroyApp (), освобождающий захваченные мидлетом ресурсы и удаляющий сам мидлет из памяти, то есть закрывает работу приложения. И самый последний метод основного класса мидлета conimandAction () интерфейса CommandListener обрабатывает назначенные события.

public void commandAction(Command c, Displayable s) { if (c ==? exitCommand) { destroyApp(false); notifyDestroyed(); } }

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

 



создаем класс Perexod public class



Листинг 5.2

Переход с экрана на экран */ // подключаем пакеты import javax.microedition.midlet.*; import javax.microedition..lcdui. *; // создаем класс Perexod public class Perexod extends MIDlet implements CommandListener { // команда выход из программы  private Command exitMidlet; // команда перехода в программе  private Command perexodTextBox; private Command perexodList;  private Command perexodAlert; // дисплей private Display mydisplay; // конструктор класса  Perexod public Perexod()  { mydisplay = Display.getDisplay(this);
// выход из приложения exitMidlet = new Command("Выход", Command.EXIT, 1);
// переход TextBox perexodTextBox = new Command("Перейти", Command.SCREEN, 2);
} // входная точка всей программы  public void startApp() { // создаем объект класса Form Form myform = new Form("Это объект класса Form");
// добавляем команду выхода из программы myform.addCommandfexitMidlet);
// добавляем команду перехода в TextBox myform.addCommand(perexodTextBox);
// устанавливаем обработчик событий для команд объекта класса Form myform.setCommandListener(this);
// отражаем текущий экран mydisplay.setCurrent(myform);
 } public void pauseApp() {} public void destroyApp(boolean unconditional) {} // обработчик событий в программе public void commandAction(Command c, Displayable d) { // обработка команды выход if (с == exitMidlet) { destroyApp(false);
notifyDestroyed();
} // обработка команды перехода в TextBox  if (с == perexodTextBox) { TextBox tb = new TextBox("TextBox", "Текст", 256, 0);
perexodList = new Command("Перейти",Coramand.SCREEN, 2);
tb.addCommand(exitMidlet);
tb.addCommand(perexodList);
tb.setCommandListener(this);
Display.getDisplay(this).setCurrent(tb);
 } // обработка команды перехода в List  if (с == perexodList) { List mylist = new List("List", List.IMPLICIT);
perexodAlert = new Command("Перейти", Command.SCREEN, 2);
mylist.addCommand(exitMidlet);
mylist.addCommand(perexodAlert);
mylist.setCommandListener(this);
Display.getDisplay(this).setCurrent(mylist);
 } // обработка команды перехода в Alert  if (с == perexodAlert) { Alert myalert = new Alert("Alert","Текст",null,null);
Display.getDisplay(this).setCurrent(myalert);
} } }

После компиляции примера пройдите по всей программе и убедитесь, что вам понятна общая идея и принцип работы смены экранов, на которых строятся все приложения в Java 2 ME.
 


public class Navigator extends MIDlet



Листинг 5.3

Навигация в приложении */ import javax.microedition.midlet.*; import javax.microedition.Icdui.*; public class Navigator extends MIDlet implements CommandListener { // команда выхода из приложения private Command exitMidlet = new Command("Выход", Command.EXIT, 1);
// команда перехода в TextBox private Command perexodTextBox = new Command("B TextBox", Command.SCREEN, 2);
// команда перехода в List private Command perexodList = new Command("B List", Command.SCREEN, 2);
 // команда перехода в Alert private Command perexodAlert = new Command("B Alert", Command.SCREEN, 2);
 // команда перехода в Form private Command perexodForm= new Command("B Form", Command.SCREEN, 2);
// объект класса Form private Form myform = new Form("Это объект класса Form");
// объект класса List private List mylist = new List("Этообъект класса List", List.IMPLICIT);
// объект класса TextBox private TextBox mytextbox = new TextBox("Это TextBox", "Текст", 256, 0);
// объект класса Alert private Alert myalert = new Alert("Это Alert","Alert исчезнет",null,null);
// объект mydisplay представляет экран телефона private Display mydisplay; public Navigator() { mydisplay = Display.getDisplay(this);
} public void startApp() { // добавить команды перехода в Form myform.addCommand(exitMidlet);
myform.addCommand(perexodTextBox);
myform.addCommand(perexodList);
myform.addCommand(perexodAlert);
У/ установка обработчика событий для Form myform.setCommandListener (this);
// отразить текущий дисплей mydisplay.setCurrent(myform);
} public void pauseApp() {} public void destroyApp(boolean unconditional) {} public void commandAction(Command c, Displayable d)  { // выход из приложения if (с = = exitMidlet) { destroyApp(false);
notifyDestroyed();
} // переход в TextBox if (с == perexodTextBox) { mytextbox.addCommand(exitMidlet);
mytextbox.addCommand(perexodForm);
mytextbox.addCommand(perexodList);
mytextbox.addCommand(perexodAlert);
mytextbox.setCommandListener(this);
mydisplay.setCurrent(mytextbox);
} // переход в List if (c == perexodList) { mylist.addCommand(exitMidlet);
mylist.addCommand(perexodForm);
mylist.addCommand(perexodAlert);
mylist.addCommand(perexodTextBox);
mylist.setCommandListener(this);
mydisplay.setCurrent(mylist);
} // переход в Alert if (c == perexodAlert) { mydisplay.setCurrent(myalert);
 } // переход в Form if (c == perexodForm) mydisplay.setCurrent(myform);
} }

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


Меню в телефоне



Рисунок 5.3. Меню в телефоне



В рассматриваемом примере мы воспользовались классом TextBox, который создает область для вывода текста. В связи с этим, на экране появится текстовая строка, изначально прописанная в программном коде в параметре text конструктора класса TextBox. Этот . текст на дисплее можно отредактировать как угодно, воспользовавшись клавишами эмулятора телефона. В нижнем левом углу экрана, вы увидите надпись Выход. Нажав на клавишу телефона под этой надписью, вы автоматически выйдете из программы. При нажатии подэкранной клавиши Выход, происходит запуск метода commandAction (), реакция которого на команду ' Выход, равносильна обработке событий для переменной exitCommand. Обработка события в данном случае подразумевает вызов двух методов - destroyApp () и notifyDestroyed(), благодаря которым происходит обнуление ссылок, если таковые имеются, и выгрузка мидлета и всего приложения из памяти телефона, возвращая- вас в меню телефона, откуда производился запуск рассматриваемой программы. В итоге весь жизненный цикл работы приложения сводится к периоду активизации программы до выхода из нее. На Рисунок 5.4 показана общая модель работы мидлета.



Мидлет



5.1. Мидлет



Приложение, написанное для мобильного телефона, может состоять из различного количества классов. Одни классы, отвечают за загрузку ресурсов, другие за обработку данных, третьи выполняют еще какие-то дополнительные функции, как программист вы вправе выбирать любую удобную для вас модель построения программы. В итоге, созданные вами классы, объединенные в одно целое, будут составлять одну программу или приложение. Все приложения, сформированные для работы в среде Java мобильных телефонов, носят название мидлет. Мидлет -это программа, написанная для мобильного телефона с использованием платформы Java 2 ME. Определять количество классов программы привилегия программиста, но среди всех классов одной программы существует один основной класс, с которого начинается работа всей программы. Этот основной класс мидлета, сердце приложения, он наследуется от класса javax.microedition.midlet. MI Diet. В этом классе описывается код, отвечающий за управление процессом создания интерфейса пользователя, объявления набора данных необходимых для работы всего приложения, создаются объекты имеющихся классов, и что самое главное, он является отправной точкой в работе приложения. Такой класс в Java 2 ME носит название основной класс мидлета.

Рабочие функции, выполняемые этим классом, практически идентичны методу main (). Помните запись, с которой начинался рабочий процесс приложений написанных на Java 2 SE:

public static void main ( String[] args )
На мобильных устройствах аналогичные действия возложены на подкласс класса MIDlet, производящий управление рабочим процессом всего приложения. В дополнение к основному классу, может создаваться ряд классов необходимых для реализации поставленной перед вами задачи. Также имеется возможность собирать несколько мидлетов в один архив. Такая комплектация программ или мидлетов помещенных в один JAR-файл носит название MIDlet suite (набор мидлетов).

В главе 2, когда объяснялась работа в среде Sun ONE Studio 4 Mobile Edition и J2ME Wireless Toolkit 2.1, в частности момент создания проекта Demo, был сформирован простейший код мидлета с названием HelloMIDlet. Этот код был сгенерирован автоматически Sun ONE Studio 4 Mobile Edition, он очень простой и дает хорошую возможность разобраться в структуре мидлета. Посмотрите на листинг 5.1, где приведен код примера HelloMIDlet проекта Demo, созданный в главе 2.
/** Листинг 5.1 Класс HelloMIDlet.java */ import javax.microedition.midlet.*; import javax.microedition.lcdui.*;  public class HelloMIDlet extends MIDlet implements CommandListener  { private Command exitCommand; private Display mydisplay;     public HelloMIDlet()     { mydisplay = Display.getDisplay(this); exitCommand = new Command("Выход", Command.EXIT, 1);     } public void startApp() { TextBox t = new TextBox(" ", "Строка текста", 256, 0); t.addCommand(exitCommand); t.setCommandListener(this); mydisplay.setCurrent(t);   } public void pauseApp() {  } public void destroyApp(boolean unconditional) { } public void commandAction(Command c, Displayable s) { if (c == exitCommand) { destroyApp(false); notifyDestroyed(); } } }
Первое, что бросается в глаза при детальном рассмотрении кода мидлета - это три метода: startApp (), pauseApp () и destroyApp (). Программисты, которые знакомы с аплетами, найдут явное сходство в структуре мидлета и аплета, даже названия в некоторой степени схожие. В аплете также имеются подобные методы: start (), stop () и destroy (). Можно сказать, что основной класс мидлета - это некий симбиоз аплета и метода main(), играющего основную и управляющую роль в приложении для мобильных устройств. Создавая свои классы и реализуя их код, вы должны возложить основные рабочие функции на основной класс мидлета. На Рисунок 5.1 показан принцип работы мобильных приложений.



Модель работы мидлета



Рисунок 5.4. Модель работы мидлета



Основной класс мидлета - это своего рода мотор всего приложения, тогда как функциональную часть лучше разбить на необходимое количество классов. Конечно, возможна интеграция всего программного кода приложения в код основного класса мидлета, но, во-первых, это непрофессионально, а во-вторых, это просто неудобно. Хорошо если вы пишете совсем маленькое приложение подобно нашему примеру, но когда речь идет о более серьезном программном продукте, надо разработать четкую структуру классов, продумать общую модель взаимодействия и в конечном итоге написать код приложения. При рассмотрении примеров этой и следующей главы мы будем пока использовать основной класс мидлета, формируя в этом классе дополнительные объекты рассматриваемых классов платформы Java 2 ME, для того чтобы не путаться в большом количестве исходных файлов. Но, начиная с главы 7, перейдем к профессиональной модели построения приложений.

 


Навигация



5.4. Навигация



Рассмотренный пример из листинга 5.2 раскрыл суть перехода с одного экрана на другой. Как вы заметили, принцип смены экраны довольно прост - достаточно добавить необходимую команду с помощью метода addCommand (), установить обработчик событий для этого экрана и создать код в методе commandAction () , адекватно реагирующий на заданные действия.

Познакомившись с моделью смены экранов и закрепив свои знания на практике, можно переходить к более осмысленной навигации в приложении. В предыдущем примере происходила последовательная смена экранов без возможности возврата либо перехода на необходимый экран. Такая структура хороша для изучения, но абсолютно не годится для серьезного приложения. Телефоны различных марок имеют собственные механизмы перехода, предоставляемые операционной системой или прошивкой мобильного телефона. Механизм, использованный в Java 2 ME для приложений созданных на этом языке, предоставляет не менее мощные, а главное, простые средства для навигации в программе. Самый простой и, как мне кажется, эффективный способ - это использовать автоматически созданное меню при помощи сервиса телефона. Когда вы добавляете к заданному экрану с присоединенным к нему объектом Displayable команды обработки в виде двух подэкранных клавиш, вы имеете всего два видимых варианта клавиш -слева и справа. Как только вы добавите с помощью функции addCommand () более двух команд, сервис телефона автоматически создаст на правой или левой подэкранной клавише телефона (в зависимости от марки производителя), выпадающее меню. При нажатии клавиши, отвечающей за меню, появится меню, отображающее полный список имеющихся команд. На Рисунок 5.7 изображено контекстное меню, созданное эмулятором телефона среды программирования J2ME Wireless Toolkit 2.1.



Переход с экрана на экран



5.3. Переход с экрана на экран



Прежде чем мы приступим к изучению основ перехода в приложении с одного экрана на другой, хочу обозначить стоящие перед нами задачи в рассмотрении средств по созданию пользовательского интерфейса. Сейчас вы имеете некоторое представление о модели работы программ для мобильных телефонов. Далее вы изучите основной способ перехода от экрана к экрану внутри приложения на простом примере. Потом код несколько усложнится и будет показан механизм навигации в программах на Java 2 ME. И уже в главе 6 будут изучены все классы пользовательского интерфейса для создания действительно красивых программ. Сейчас мы идем от простого к сложному и я хочу предложить вам новый пример кода, на основе которого будет изучена схема перехода с одного экрана на другой. Попутно мы задействуем все четыре высокоуровневых класса TextBox, Form, List и Alert.

Прежде чем коснуться непосредственно программирования любого приложения, нужно уделить внимание теоретической части создаваемой программы. Лично я, когда разрабатываю некую программу для мобильного телефона, беру чистый листок бумаги, карандаш и рисую предполагаемый набор экранов, указывая на связь между ними с помощью стрелочек. Это, конечно, не язык UML, но достаточно просто и эффективно. На Рисунок 5.6 даются все четыре дисплея и связь между ними.



Переход с экрана на экран



Рисунок 5.6. Переход с экрана на экран



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

import javax.microedition.midlet.*; import javax.microedition.Icdui.*.

Затем создаем класс Perexod, наследуемый от класса MIDlet.

public class Perexod extends MIDlet implements CommandListener

Теперь необходимо создать объекты класса Command. Объект exitMidlet нужен для выхода из программы. Код, реализующий это событие аналогичен коду из предыдущего примера, рассмотренного в листинге 5.1. И еще три объекта будут служить для перехода от экрана к экрану:

private Command exitMidlet; private Command perexodTextBox; private Command perexodList; private Command,perexodAlert; private Display mydisplay;

Названия этих объектов достаточно информативны и в объяснении не нуждаются. Далее очередь подошла к конструктору класса Perexod. Первым делом сохраним ссылку на Display в переменной mydisplay:

mydisplay = Display.getDisplay(this);

Следующим шагом создадим два объекта класса Command, один для выхода из программы, другой для перехода на экран представленный классом TextBox.

exitMidlet = new Command("Выход",Command.EXIT,1); perexodTextBox = new Command("Перейти",Command.SCREEN,2);

Создание этих объектов в конструкторе - не обязательное условие. Просто я основывался на предыдущем примере и оставил примерную структуру приложения для понимания. На самом деле все четыре объекта класса Command можно было инициализировать еще при их объявлении .в начале класса MainMidlet, что более читабельно. Следующим кодом за конструктором идет метод startАрр (), внутри которого создается объект класса Form. Добавим при помощи метода addCommand () команду Выход - это выход из приложения и команду Переход - это переход на экран представленный классом TextBox. 'Назначим обработчик событий классу Form методом setCommandListener () и присоединим объект myform класса Form к текущему дисплею при помощи метода setCurrent().

public void startApp() { Form myform = new Рогт("Это объект класса Form"); myform.addCommand(exitMidlet); myform.addCommand(perexodTextBox); myform.setCommandListener(this);  // отражает текущий экран mydisplay.setCurrent(myform); }

Когда вы запустите программу или войдете в рабочий цикл мидлета, то автоматически инициализируются объекты классов и конструктор класса Perexod, а работа программы начнется с вызова метода startApp (). Теперь необходимо назначить соответствующие действия клавишам перехода в методе commandAction () интерфейса CommandListener для обработки пользовательских команд. Переход по кнопке Выход вам уже знаком из предыдущего примера, поэтому оставим все почти без изменения, за исключением информационной команды exitMidlet.

if (с == exitMidlet) { destroyApp(false); notifyDestroyed(); }

А теперь вплотную займемся командой Перейти. Что от нас требуется? В момент запуска программы мы попадаем на экран представленный классом Form посредством команды perexodTextBox, а требуется прейти на экран представленный классом TextBox. Для создания обработчика событий команды Перейти нужно сформировать объект класса TextBox, позаботиться о следующей кнопке перехода perexodList для перехода на экран, представленый классом List, добавить команду Выход для выхода из программы и команду Перейти. Осталось добавить обработчик событий и присоединить созданный TextBox к текущему экрану. Смотрим, что у нас получилось:

if (с == perexodTextBox) { TextBox tb = new TextBox("TextBox", "Текст", 256, 0); perexodList = new Command("Перейти", Command.SCREEN, 2)*; tb.addCommand(exitMidlet); tb.addCommand(perexodList); tb.setCommandLi'stener (this) ; Display.getDisplay(this).setCurrent(tb); }

Обратите внимание на последнюю строку кода в теле условного оператора:

Display.getDisplay.(this) . setCurrent (tb) ;

В данном случае присоединяется созданный объект tb класса TextBox к текущему экрану. Мы говорим о смене экранов для создания четкого и информативного пользовательского интерфейса, на самом деле смены экранов в буквальном смысле не происходит. Существует только один дисплей, назначенный для класса Displey, который отвечает за то, что будет нарисовано на экране телефона, а именно, какой из объектов Displayable. Только один объект Displayable может быть отображен за один раз на экране. То есть существует всего один физический дисплей, к которому присоединяются необходимые объекты классов пользовательского интерфейса через обработку событий. Имеющийся экран просто постоянно перерисовывается, отображая тот или иной объект востребованного класса, а иначе говоря, к текущему дисплею присоединяется объект класса, создавая иллюзию смены экранов. Системные ресурсы телефонов пока малы, поэтому приходится идти на такие хитрости.

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

if (с == perexodList) { List mylist = new List("List", List.IMPLICIT); perexodAlert = new Command("Перейти", Command.SCREEN, 2); mylist.addCommand(exitMidlet); mylist.addCoiranand(perexodAlert); mylist.setCommandListener(this); Display.getDisplay(this).setCurrent(mylist); }

Позаботившись о переходе на экран представленный классом Alert и о выходе из приложения, можно создать код для объекта Alert, который впоследствии можно присоединить к текущему экрану. Класс Alert несколько специфичен, это вам станет понятно как только вы откроете окно, отвечающее за отображение объекта. Попробуйте после компиляции рассмотренного примера сделать для Alert команду Выход, и посмотрите, что получится. Теперь соединим рассмотренный код в одно целое, получив готовую программу, представленную в листинге 5.2. Пример также можно найти на прилагаемом к книге компакт-диске в папке \Code\Listing5_2\src.

/**



Пользовательский интерфейс



5.2. Пользовательский интерфейс



Когда мы рассматривали механизм работы примера из листинга 5.1, я думаю, вы подметили некий поэкранный принцип отображения информации на дисплее. Первый экран показывал список доступных приложений, после выбора одного из них вы попадали на экран этого приложения. Нажав кнопку Выход, происходило возвращение к экрану выбора. В Java 2 ME программах такая схема поэкранного отображения информации является основной. Если вы никогда не обращали на это внимания при работе со своим телефоном, то самое время взять его и пощелкать джойстиком. В приложениях для мобильных телефонов основанных на экранах в Java 2 ME отсутствуют окна и фреймы в отличие от Java 2 SE. Телефоны ограничены в системных ресурсах и разнообразная красивая роскошь, к сожалению не позволительна для этих маленьких устройств. Поэтому при создании конечного продукта стоит с особой тщательностью продумывать основные составляющие будущего приложения. Основываясь на поэкранном отображении информации, необходимо создавать интуитивно понятную структуру приложения, образуя при этом четкую экранную навигацию. Если пользователь заблудится в вашей программе, он просто удалит ее из памяти телефона и никогда к ней больше не вернется, а вы потеряете потенциального покупателя.

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

Платформа Java 2 ME обладает пакетом javax.microedition.lcdui, включающим в себя классы для работы с пользовательским интерфейсом UI (user interface). Большое количество классов, входящих в этот пакет, будут подробно рассматриваться в следующей главе. Самым главным классом пользовательского интерфейса является класс Displayable. С основы абстрактного класса Displayable происходит построение основной части графического интерфейса приложения. На Рисунок 5.5 показана структура пользовательского интерфейса пакета javax.microedition.lcdui.



Принцип работы приложения



Рисунок 5.1. Принцип работы приложения



Сейчас мы вкратце разберем код примера HelloMIDlet проекта Demo, а потом перейдем к более детальному анализу схемы работы приложений в Java 2 ME. Первые две строки кода из листинга 5.1 - это библиотеки импорта.

import javax.microedition.midlet.*; import javax.microedition. Icdui.*;
В этих строках происходит импорт двух пакетов платформы Java 2 ME. Первый пакет javax.microedition.midlet.* содержит класс MIDlet, с помощью которого происходит связь с MIDP. Каждый код создающий основной класс мидлета обязан импортировать этот пакет. Второй пакет содержит классы, позволяющие создавать пользовательский интерфейс приложения. В следующей главе будут подробно рассмотрены все классы пользовательского интерфейса. Импорт двух пакетов дает возможность задействовать все имеющиеся в этих пакетах интерфейсы, классы, методы и константы, необходимые для работы всего создаваемого приложения. Следующая строка кода:

public class HelloMIDlet extends MIDlet implements CommandListener
создает основной класс мидлета, наследуемый от суперкласса MIDlet, реализуя при этом методы startApp(), pauseApp() и destroyApp(). Также задействуется интерфейс CommandListener, необходимый для обработки событий происходящих в приложении при помощи метода commandAction(). Далее идут две строки создающие объекты классов Command и Display.

private Command exitCommand; private Display mydisplay;
С помощью переменной exitCommand осуществляется выход из приложения посредством метода commandAction (). Переменная mydisplay будет представлять дисплей телефона при помощи абстрактного класса Display, играющего роль диспетчера телефонных экранов. В конструкторе класса HelloMIDlet инициализируются объекты exitCommand и mydisplay.

public HelloMIDlet() { mydisplay = Display.getDisplay(this); exitCommand = new Command("Выход",Command.EXIT, 2); }
В конструкторе класса HelloMIDlet, переменная mydisplay получает ссылку на объект Display при помощи метода getDisplay (). Давайте разберемся эти действия подробно. Вы наверно заметили, что объект Display явно не создается при помощи ключевого слова new. Если быть совсем точным, вы просто не можете этого сделать. Объект класса Display создается автоматически с помощью сервисов телефона для каждого мидлета. Класс Display играет роль диспетчера телефонных экранов, на которые проецируется в итоге все то, что вы будете видеть на дисплее телефона. В телефоне существует всего один основной экран и поэтому в отдельный промежуток времени может быть отражен только один экран, за который отвечает класс Display. С помощью метода getDisplay (), основной класс мидлета получает ссылку на класс Display и содержит ее в переменной mydisplay. В последствии, для того чтобы отразить содержимое текущего дисплея, необходимо воспользоваться методом setCurrent (), например следующим образом:

mydisplay.setCurrent();
Вторая и последняя строка кода в конструкторе класса HelloMIDlet () создает экземпляр класса Command и инициализирует созданный ранее объект exitCommand. Класс Command создает набор информации или набор команд, которые можно отобразить на экране телефона для обработки событий полученных от пользователя. На основе определенного набора команд с помощью интерфейса CommandListener происходит обработка фактических действий пользователя. Посмотрите на Рисунок 5.2, где на дисплее показана команда Выход, расположенная под экранной клавишей телефона.



Структура пользовательского интерфейса



Рисунок 5.5. Структура пользовательского интерфейса



От класса диспетчера Display зависит, какой из классов Displayable будет отображен на экране. В свою очередь только один класс Displayable может быть единовременно показан на экране. То есть, объект класса TextBox, грубо говоря, существует в своем экране, объект класса List - в своем и оба объекта не могут существовать вместе на одном экране, определяя тем самым правило поэкранного отражения информации на дисплее телефона.

Далее в иерархии структуры пользовательского интерфейса, показанного с помощью Рисунок 5.5, идут два абстрактных класса: Screen и Canvas. На этой стадии происходит разделение классов пользовательского интерфейса на высокоуровневый класс, назначенный классу Screen и всей его дальнейшей иерархии наследования и низкоуровневый класс Canvas. Оба класса создают структуру интерфейсов, разделенную на высокоуровневый и низкоуровневый пользовательский интерфейсы.

Высокоуровневый интерфейс содержит средства для работы с пользовательским интерфейсом, созданные на основе классов шаблонов, использование которых приводит к построению жестко заданного интерфейса. Например, задействованный в исходном коде HelloMIDlet проекта Demo класс TextBox, не может никаким образом изменить экран телефона. Экран представленный классом TextBox - это текстовый контейнер, в котором можно осуществлять вывод, удаление и редакцию текста и не более того. То есть классы высокоуровневого интерфейса - это жестко заданная модель отображения пользовательского интерфейса на экране телефона, с помощью которых программист организует навигацию, списки, меню, текстовые контейнеры, группы выбираемых элементов и так далее.

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

На Рисунок 5.5 была дана часть пакета javax.microedition.lcdui.*, потому что классы Canvas и GameCanvas будут подробно рассматриваться соответственно в главах 7 и 8. Рассмотрим некоторые характеристики классов Alert, TextBox, Form и List представляющие высокоуровневый интерфейс:

 Alert - предоставляет возможность в создании уведомлений или сообщений об ошибках в виде отдельных экранов;  TextBox - массив данных содержащий текстовую информацию с возможностью ее редакции;  Form - экранный контейнер, в котором можно разместить различные элементы интерфейса с помощью дополнительных подклассов класса Item;  List - список элементов, позволяющий производить выбор различных операций.

 


С этой главы начинается непосредственно



В этой главе...

С этой главы начинается непосредственно описание работы с кодом. Специфика Java 2 ME приложений несколько своеобразна, но совсем несложная. Достаточно разобраться в общей модели построения программ и все сразу станет понятно.

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


Живописно изображает и отчасти



Рисунок 5.8 живописно изображает и отчасти решает поставленную перед нами задачу.

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

public class Navigator extends MIDlet  implements CommandListener



Рисунок 5.8. Схема перехода с экрана на экран


В исходном коде до строк вызова конструктора класса Navigator, добавим объект, содержащий команду Выход.

private Command exitMidlet = new Command("Выход", Command.EXIT, 1);

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

private Command perexodTextBox = new Command("В TextBox", Command. SCREEN, 2) ; private Command perexodList = new CommandC'B List", Command.SCREEN, 2); private Command perexodAlert = new CommandC'B Alert", Command.SCREEN, 2) ; private Command perexodForm = new CommandC'B Form", Command.SCREEN, 2) ;

Информативные названия всех объектов понятны, но, естественно, выбранные мною названия ни к чему вас не обязывают. Созданные объекты являются объектами класса Command, отвечающего за создание команд, которые в последствии можно определить для каждого из классов Form, TextBox, List и Alert. Позже, в коде мидлета, мы будем задавать соответствующие блоки обработки событий непосредственно в методе commandAction () при помощи оператора if и созданных объектов.

Теперь нам нужно объявить и инициализировать объекты четырех классов Form, TextBox, List и Alert.

private Form my form = new Рогт.("Это объект класса Form") ; private List mylist = new List("Это объект класса List", List.IMPLICIT); private TextBox mytextbox = new TextBox("Это TextBox", "Текст", 256, 0); private Alert myalert = new Alert("Это Alert","Alert исчезнет",null,null); private Display mydisplay;

В конструкторе класса Navigator происходит инициализация объекта

mydisplay. public Navigator() { mydisplay = Display.getDisplay(this); }

Следующая наша задача - это реализация метода startApp (). Сейчас необходимо решить какой из классов будет первым появляться на экране и добавить к нему команды перехода в другие классы, а также команду выхода из приложения. В предыдущем примере первым появлялся класс Form. Его и определим как основной объект, в который попадет пользователь, запускающий приложение.

public void startApp() { myform.addCommand(exitMidlet); myform.addCommand(perexbdTextBox); myform.addCommand(perexodList); myform.addCommand(perexodAlert); myform.setCommandListener(this); mydisplay.setCurrent(myform); }

Последняя строка метода startApp() отображает объект myform на дисплее со всеми имеющимися командами. Как уже говорилось, командам, которым не хватит телефонных клавиш, будет автоматически создано свое собственное меню.

После того как вы попадете в основное окно приложения, которое мы определили для объекта myform, над левой или правой подэкранной клавишей появится команда выхода из приложения и команда Menu. При нажатии на клавишу Menu, на экране телефона появится всплывающее Меню с добавленными ранее командами перехода на экраны, представленные классами TextBox, List и Alert.

Следующей нашей задачей является написание кода для обработки событий созданных команд в методе commandAction (). Код, обрабатывающий команду Выход из приложения, идентичен коду из примера в листинге 5.2 и в большинстве рассматриваемых впоследствии примеров останется таковым. Дальнейшие действия состоят в обработке команды перехода на экран, представленный классом TextBox.

if (с == perexodTextBox) { mytextbox.addCommand(exitMidlet); mytextbox.addCommand(perexodForm); mytextbox.addCommand(perexodList); mytextbox.addCommand(perexodAlert); mytextbox.setCommandListener(this); mydisplay.setCurrent(mytextbox);  }

Сразу после того, как пользователь попадет на экран, представленный классам Form, и в контекстном меню выберет команду Перейти в TextBox, произойдет обработка блока команд perexodTextBox. Добавляются все команды к объекту mytextbox, устанавливается обработчик событий и в итоге отображается текущий экран, содержащий все созданные компоненты объекта mytextbox. Точно так же как и на экране с объектом myform существует меню перехода и кнопка выхода.

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

/ * *



Класс ChoiceGroup



6.2.1. Класс ChoiceGroup



С помощью класса ChoiceGroup можно встраивать в форму группу элементов. Группы элементов делятся на три типа: эксклюзивный (EXCLUSIVE), множественный (MULTIPLE) и всплывающий (POPUP). Посмотрите на рис 6.3, где показан эмулятор мобильного телефона, показывающий все три группы элементов.



Методы класса Alert



6.3.1. Методы класса Alert



Существует множество методов класса Alert, все они призваны создавать более насыщенные и информационные сообщения. Рассмотрим методы класса Alert.

void addCommand(Command cmd) — добавляет команду;  int getDef aultTimeout () - получает время для представления уведомления. Можно воспользоваться переменной FOREVER для постоянного представления экрана с объектом класса Alert;  Image get Image () - получает изображение для экрана представленного классом Alert;  Gauge get Indicator () - этот метод позволяет воспользоваться графическим измерителем класса Gauge;  String getString() - получает текстовую строку;  int getTimeout () - получает заданное время для представления уведомления;  AlertType get Туре () - определяет тип используемого уведомления;  void removeCommand (Command cmd) - удаляет команду;  void setCommandListener(CommandListener 1) —.устанавливает обработчик событий;  void setlmage (Image img) - устанавливает изображение;  void setlndicator(Gauge indicator) - устанавливает индикатор измерителя для использования класса Gauge;  void setString(String.str) - устанавливает строку текста;  void setTimeout (int t ime)-устанавливает время;  void setType (AlertType type) - устанавливает тип уведомлений или информационных сообщений.


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

/**



Методы класса Form



6.1.1. Методы класса Form


int append (Image img) - добавляет в форму одно изображение. Класс Image дает возможность загрузить изображение на экран телефона, это может быть фон дисплея, элемент интерфейса;  int append (Item item) - этот метод добавляет любой из доступных компонентов класса Item в созданную форму;  int append(String str) - добавляет в форму строку текста;  void delete (int itemNum) - удаляет компонент, ссылающийся на параметр itemNum;  void deleteAll () - удаляет все компоненты из имеющейся формы;  Item get (int itemNum) - получает позицию выбранного компонента;  int getHeight () - возвращает высоту экрана в пикселях доступную для встраиваемых компонентов;  int getwidth () - возвращает ширину экрана в пикселях доступную для встраиваемых компонентов;  void insert (int itemNum, Item item) — вставляет компонент в форму до определенного компонента;  void set (int itemNum, Item item) - устанавливает компонент, ссылающийся на компонент itemNum, заменяя при этом предшествующий компонент;  void setltemStateListener(ItemStateListener iListener) -устанавливает переменную iListener для формы, заменяя при этом предыдущую переменную iListener;  int size ()-получает количество компонентов в форме.


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

Form myform = new Form("Пример");  myform.append (iteml); myform.append (item2);
В этом примере в созданную пустую форму добавляются два объекта. Оба объекта, разумеется, должны быть созданы в коде. Точно так же можно воспользоваться всеми методами класса Form для редактирования создаваемой формы. Добавленные в форму компоненты организованны в виде колонок и обычно располагаются по ширине всего экрана. На Рисунок 6.1 изображен эмулятор с несколькими компонентами интерфейса.



Методы класса Image



6.6.1. Методы класса Image



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

static Image createlmage(byte[] imageData, int imageOff-set, int imageLength) -загружает изображение учитывая смещение и длину f1 байтах;  static Image createlmage (Image source) - загружает изображение из файла;  static Image createlmage(Image image, int x, int y, int width, int height, int transform) - загружает изображение в заданное место, определенное координатами, с возможностью трансформации изображения. Параметр transform устанавливает необходимую трансформацию с помощью класса Sprite и константных значений:  Sprite. TRANS_NONE - изображение копируется без трансформации;  Sprite.TRANS_ROT90 - трансформирует изображение по часовой стрелке на 90°;  Sprite.TRANS_ROT180- трансформирует изображение по часовой стрелке на 180°;  Sprite.TRANS_ROT270 - трансформирует изображение по часовой стрелке на 270°;  static Image createlmage (InputStream stream) -загружает изображение из потока;  static Image createlmage(int width, int height) -загружает изображение в заданные размеры;  static Image createlmage (String name) - загружает изображение из ресурса;  static Image createRGBImage(int[] rgb, int width, int height, boolean processAlpha) - загружает изображение, учитывая цветовую компоненту ARGB;  Graphics getGraphics () - создает графический объект для представления изображения;  int getHeight () - получает высоту изображения;  int getwidth () — получает ширину изображения.


В листинге 6.11 происходит загрузка изображения в приложение, но без использования объекта класса ImageItem, который использовался при рассмотрений примера в листинге 6.6 из раздела 6.8. В листинге 6.6 применялась ссылка на объект класса Image, в этом примере объект классу Image используется напрямую

/**



Методы класса List



6.4.1. Методы класса List



Класс List имеет множество методов, с помощью которых можно производить редакцию списка элементов, выбор заданного элемента и многое другое. Разберем часть методов класса List.

int append(String stringPart, Image imagePart) —добавление списка элементов;  void delete (int elementNum) - удаление заданного элемента из списка;  void deleteAll() - удаление всех элементов;  Font getFont(int elementNum) - получает шрифт для заданного элемента в списке;  Image getlmage(int elementNum) - получает изображение для заданного элемента в списке;  int getSelectedFlags(boolean[] selectedArray_return)-возвращает состояние всех элементов в виде массива данных;  int getSelectedlndext) - получает выбранный индекс элемента в списке;  String getString(int elementNum) - получает строку текста для выбранного элемента из списка;  void insert(int elementNum, String stringPart, Image imagePart) - вставляет элемент в список до указанного номера элемента в списке;  boolean isSelected(int elementNum) - получает выбранный элемент из списка;  void removeCommand (Command cmd) - удаляет команду для списка;  void set(int elementNum, String stringPart, Image imagePart) - вставляет новый элемент в список в замен предшествующего;  void setFont(int elementNum, Font font) - устанавливает шрифт заданному элементу в списке;  void setSelectCommand (Command command) - этот метод предназначен для работы с типом IMPLICIT. Когда используется такой тип списка, то выбирается элемент, на котором сфокусирована в данный момент строка состояния. Этот метод позволяет определить, на каком элементе сфокусировано внимание пользователя. При этом используется такая запись: List .SELECT_COMMAND. для определения выбранного элемента в списке;  void setSelectedFlags(boolean[] selectedArray)-устанавливает состояние выбранных элементов;  void setSelectedlndexfint elementNum, boolean selected) - устанавливает индекс выбранного элемента в списке;  void setTitle (String s) - добавляет название в список элементов;  int size () - с помощью этого метода можно узнать количество элементов в списке.


Теперь давайте создадим пример, описывающий основные возможности класса List. Класс List может создавать три списка элементов: Exclusive, Multiple и Implicit. Используем эту возможность и создадим код, реализующий все три типа. Основная идея создания примера для класса List сводится к следующему: при входе в приложение пользователь попадает в главное окно со списком из двух элементов Multiple и Implicit, а сам список этих двух элементов будет создан на основе типа Exclusive. Ко всем элементам списка будут загружаться свои иконки. Выбрав один из двух элементов списка курсором, пользователь должен нажать клавишу команды Выбор для перехода в программе. Оба элемента списка Multiple и Implicit будут представлять два разных типа списка. Выбрав один из элементов Multiple или Implicit, пользователь попадает на новый экран. Каждый из выбранных списков будет содержать ряд элементов иллюстрирующих работу типов Multiрlе и Implicit. Выбирая элементы из этих списков, пользователь будет получать информационное сообщение. В листинге 6.9 исходный код примера..

/**



Методы класса Ticker



6.5.1. Методы класса Ticker



В составе класса Ticker существует всего два метода для получения и установки необходимой строки текста для приложения.

String getstring () - получает строку текста, заданную для объекта класса Ticker;  void setstring (String str) - устанавливает строку текста для отображения ее на экране телефона с помощью объекта класса Ticker, заменяя ее новой строкой.


Также имеется возможность воспользоваться еще двумя методами абстрактного класса Displayable. Оба метода выполняют аналогичные действия методам класса Ticker, но при этом позволяют встраивать объект класса Ticker непосредственно в форму, то есть экран представленный классом Form. Разберем эти два метода:

 void setTicker (Ticker ticker) - устанавливает новую бегущую строку, заменяя предыдущую;  Ticker getTicker () - получает используемую строку текста.


Оба этих метода дублируют по сути методы класса Ticker. В листинге 6.10 приводиться образец применения класса Ticker.

/**



Класс DateField



6.2.2. Класс DateField



Это, пожалуй, самый простой класс из всех имеющихся в иерархии класса Item. С помощью класса DateField возможно произвести установку необходимой даты и времени. Используемый интерфейс для отображения даты и времени элементарный и практически все действия по установке заданных параметров даты и времени уже реализованы программно. На Рисунок 6.4 изображен эмулятор телефона, отображающий текущее время.

В составе класса DateField имеется в наличии два конструктора, для создания объектов этого класса, рассмотрим их. Первый конструктор:

public DateField(String label, int mode);

Параметры конструктора класса DateField:

label - строка текста;  mode — с помощью этого параметра конструктора, устанавливается, какой именно из компонентов класса DateField будет воссоздан на экране.


Имеется возможность вывести дату с помощью значения DATE, и время, задав значение TIME. Также можно пользоваться комбинированным способом DATE_TIME для отображения обоих компонентов вместе.

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

public  DateField(String label, int mode, TimeZone timeZone)

Параметры конструктора класса DateField:

 label - строка текста;  mode - установка заданных компонентов класса DateField;  timeZone - это объект класса TimeZone, с помощью которого можно определить часовой пояс. Например:


TimeZone v  =  TimeZone.getTimeZone("GMT");

Класс DateField содержит всего четыре метода:

 Date getDate() - возвращает текущую дату;  void setDate(Date date) - устанавливает новую дату;  int get!nputMode() - получает установленные компоненты DATE, TIME или DATA_TIME;  void setlnputMode (int mode) - устанавливает компоненты DATE, TIME или DATE_TIME.



Класс TextField



6.2.3. Класс TextField



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

public TextField(String  label, String text, int maxSize, int  constraints)

Параметры конструктора класса Text Field:

 label - метка, название для редактируемого поля;  text - строка текста. Поле может и не содержать текст;  maxSize - максимальное количество символов в поле;  constraints - входное ограничение, с помощью которого можно задавать, что именно должно принимать данное поле, например цифры, буквы или символы, задается ограничение с помощью следующих констант:  static int ANY - можно вводить любой текст;  static int DECIMAL - можно вводить дробные числа;  static int EMAILADDR - используется для адреса электронной почты;  static int NUMERIC-для ввода только целого числа;  static int PASSWORD - используется при вводе пароля;  static int PHONENUMBER - для ввода телефонного номера;  static int URL - адрес сайта в Интернет.


Как видите, предусмотрены практически все варианты, остается только подставлять требуемые значения и наслаждаться простотой программирования под Java 2 ME. Использование вышеперечисленных директив в Java 2 ME традиционно и, например, для ввода адреса сайта может быть следующая запись:

TextField tf  =  new TextField("Адрес","",20,TextField.URL);

Методы класса TextField

Класс TextField содержит четырнадцать методов, некоторые из них мы сейчас рассмотрим.

 void delete (int offset, int length) - удаляет текст или заданный символ;  int ,getCaretPosition() - получает позицию каретки для печати символов;  int getChars (char [ ] data) - копирует текст в символьный массив данных;  int getMaxSize() - определяет максимально доступное количество символов для размещения в классе TextField;  String getString() - получает строку текста;  void insert (char [] data, int offset, int length, int position) - вставляет в заданную позицию массив символьных данных;  void insert (String src, int position) - вставляет в заданную позицию строку текста;  void setChars(char[] data, int offset, int length) —устанавливает из символьного массива данные в заданную позицию, при этом заменяя предыдущие данные;  int size ()-определяет размер содержимого в TextField на данный момент.


Теперь перейдем непосредственно к примеру, реализующему возможности класса TextField. Создадим пустую форму, и вставим в нее поля в виде адресной книги. В листинге 6.3 дается код всего примера.

/**



Класс Stringltem



6.2.4. Класс Stringltem



Рассматриваемый класс позволяет интегрировать в форму строку текста, состоящую из двух частей - метки и заданного текста. Строка текста, выводимая на экран, не может быть изменена или отредактирована - это статический текст, жестко заданный в параметрах конструктора класса StringItem при создании объекта этого класса. Имеется два конструктора класса StringItem, разберем их устройство.

public StringItem(String  label,String text)

Параметры конструктора класса Stringltem:

 label - метка для строки текста;  text - строка текста.


Второй конструктор класса Stringltem имеет три параметра и позволяет выбирать способ отображения текстовой информации.

public  Stringltem(String label, String text, int appearanceMode)

Параметры конструктора Stringltem:

 label - метка для строки текста;  text - строка текста;  appearanceMode - этот параметр содержит большое количество предустановленных значений, используя которые вы сможете отформатировать текст, например, поместив его в кнопку и создав при этом команду, реагирующую на нажатие данной кнопки.


Значения, устанавливающие выше перечисленные действия содержаться в пакете javax.microedition.lcdui.Item, рассмотрим несколько из них.

 BUTTON - создает кнопку с текстом;  HYPERLINK - создает гиперссылку;  LAYOUT_BOTTOM - выравнивание к нижней части экрана;  LAYOUT_CENTER - выравнивание по центру экрана;  LAYOUT_TOP - выравнивание к верхней части экрана;  LAYOUT_LEFT - выравнивание к левой части экрана;  LAYOUT_RIGHT - выравнивание к правой части экрана.


При создании примера к классу Stringltem обязательно воспользуемся некоторыми значениями для параметра appearanceMode в конструкторе класса Stringltem.

Методы класса Stringltem

 int getAppearanceMode () - возвращает заданный способ отображения текста на экране;  Font getFont () - получает шрифт текста;  String getText () - получает текст для класса Stringltem;  void setFont(Font font) - устанавливает шрифт текста;  void setPref erredSize (int width, int height) -задает ширину и высоту текста;  void setText (String text) - устанавливает текст для класса StringItem.


Пример, который будет предложен для класса StringItem, создаст форму при помощи класса Form и разместит в форме текст. Первая строка текста выполнена в виде простой статической надписи, вторая сделана как гиперссылка. Выделив эту строку текста и нажав кнопку на телефоне перейти, вы попадете на экран с новой формой. А последняя третья строка текста выполнена просто в виде кнопки. Рассмотрим листинг 6.4 иллюстрирующий работу данного примера.

/ * *



Класс Spacer



6.2.5. Класс Spacer



Класс Spacer подвигает элемент на экране телефона, создавая тем самым свободное пространство с указанными размерами. Именно за создание свободного пространства на экране отвечает класс Spacer. При создании объекта класса используется один конструктор с двумя параметрами, при помощи которых задается создаваемое пространство на экране. Конструктор класса Spacer выглядит следующим образом:

public Spacer(int minWidth,int minHeight);

Параметры конструктора Spacer:

 minWidth - ширина в пикселях;  minHeight - высота в пикселях.


Класс Spacer имеет четыре метода, все они просты и не нуждаются в пояснениях, в приложении 2 находится справочник по платформе Java 2 ME, в котором вы сможете найти описание существующих методов класса Spacer. Чтобы показать работу класса Spacer, рассмотрим простой пример, где создается область в пятьдесят пикселей по ширине и ноль по высоте, благодаря чему элемент, размещенный в форме, сдвигается на указанное пространство вправо. В качестве элемента встроенного .в форму используется класс TextField. В листинге 6.5 дается исходный код примера.

/**



Класс ImageItem



6.2.6. Класс ImageItem



С помощью класса Imageltem возможна загрузка изображения в форму представленную классом Form. Изображением может быть любая картинка формата PNG (Portable Network Graphics - формат портативной сетевой графики), выполненная в виде иконки, фотографии, заставки, фона и так и далее. Имеются два конструктора класса Imageltem. Первый конструктор содержит четыре параметра, рассмотрим этот конструктор:

public ImageItem(String label, Image img, int layout, String alt Text)

Параметры конструктора ImageItem:

label - метка;  img - объект класса Image, содержащий изображение;  layout - форматирует загружаемое изображение на экране телефона, с помощью использование следующих директив:  public static final int LAYOUT_DEFAULT - размещение изображения по умолчанию;  public static final int LAYOUT_LEFT - размещение изображения со сдвигом к левой стороне экрана;  public static final int LAYOUT_RIGHT - размещение изображения со сдвигом к правой стороне экрана;  public static final int LAYOUT_CENTER - размещение изображения со сдвигом к центру экрана.  altText - информационный текст, используемый взамен загружаемого изображения. Если текст не используется - этот параметр нужно установить в значение null.


Второй конструктор класса Imageltem имеет на один параметр больше и выглядит следующим образом:

public  Imageltem(String  label,  Image  img, int   layout, String altText int  appearanceMode)

Параметры конструктора Imageltem:

 label - метка;  img - объект класса Image, содержащий изображение;  layout-форматирование загружаемого изображения на экране телефона;  altText - текст, использующийся в замен загружаемого изображения;  appearanceMode - этот параметр содержит ряд значений:  BUTTON - создает кнопку с текстом;  HYPERLINK - создает гиперссылку;  LAYOUT_BOTTOM - выравнивание к нижней части экрана;  LAYOUT_CENTER - выравнивание по центру экрана;  LAYOUT_TOP - выравнивание к верхней части экрана;  LAYOUT_LEFT - выравнивание к левой части экрана;  LAYOUT_RIGHT - выравнивание к правой части экрана.


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

При загрузке изображений с помощью класса ImageItem существует ряд нюансов, на которые необходимо обратить внимание. Класс ImageItem является подклассом класса Image, прежде чем воспользоваться классом ImageItem, необходимо создать объект класса Image. Затем поместить или загрузить в объект класса Image изображение и только потом воспользоваться классом ImageItem для размещения изображения на экране представленного объектом класса Form. Создавая объект класса ImageItem, вы создаете своего рода контейнер для содержания ссылки на объект Image. Рассмотрим небольшой фрагмент кода, иллюстрирующий создание и загрузку изображения:

Image  a  =   Image.createlmage("/ris.png");  Imageltem b  =  new  Imageltem("



Класс Gauge



6.2.7. Класс Gauge



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

Класс Gauge имеет всего один конструктор, необходимый при создании объекта этого класса. Разберем конструктор класса Gauge:

publicGauge(String label, boolean interactive, int maxValue, int initialValue)



Иерархия суперкласса Item



Рисунок 6.2. Иерархия суперкласса Item


 ChoiceGroup - это группа связанных, элементов для дальнейшего выбора предполагаемых действий;  Gustomitem - с помощью этого класса можно добавлять различные графические элементы в форму;  DateField- класс, с помощью которого имеется возможность редактировать время и дату;  Gauge- допускает графическое отображение диаграмм, процессов загрузки;  ImageItem - осуществляет показ изображения на экране телефона;  Spacer - задает определенное по размеру пространство;  Stringltem- с помощью этого класса можно создать произвольный текст. Этот класс не допускает редактирования, он лишь отображает информацию; TextField - предоставляет текстовые поля для редакции.


Любой из рассмотренных классов наследуется из суперкласса Item и может быть добавлен на экран, созданный классом Form. Каждый компонент класса Item содержит с левой стороны область; где при желании можно отобразить изображение в виде иконки. При перемещении компонента, иконка также перемещается вместе с компонентом. Класс Item с помощью имеющихся вcего составе директив задает, в основном, формат отображения для любого компонента. Формат определяет заданную ширину, высоту или выравнивание компонентов в форме, а также класс Item имеет множество методов осуществляющих контроль над компонентами.

Методы класса Item

 voidaddCommand (Command cmd) - добавляет команду к компоненту;  String getLabel () - получает метку объекта Item;  int getLayout () - использует следующие директивы для размещения компонентов в форме:  LAYOUT_LEFT - выравнивание по левой стороне;  LAYOUT_RIGHT - выравнивание по правой стороне;  LAYOUT_CENTER - выравнивание по центру;  LAYOUTJTOP - выравнивание к верхней области формы;  LAYOUT_BOTTOM - выравнивание по нижней стороне экрана;  LAYOUT_VCENTER - вертикальное выравнивание по центру. Горизонтальная и вертикальная директивы могут комбинироваться при помощи оператора «|».  int getMinimumHeight() -получает минимальную высоту для компонента;  int getMinimumWidth () - получает минимальную ширину для компонента;  int getPreferredHeight () - получает предпочтительную высоту компонента;  int getPreferredWidth() - получает предпочтительную ширину компонента;  void notifyStateChanged() - компонент, содержащийся в форме. Уведомляет объект ItemStateListener о своем состоянии;  void removeCommand {Command cmd) - удаляет команду из компонента;  void setDefaultCommand (Command cmd) - встроенная команда по умолчанию для данного компонента;  void setltemCommandListener(ItemCommandListener 1)-устанавливает обработку событий для компонента;  void set Label (String label) - устанавливает назначенную метку для компонента;  void setLayout (int layout) - устанавливает директивы для форматирования компонента;  void setPreferredSize(int width, int height) -устанавливает оптимальную высоту и ширину компонента.


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

 


Изображает эмулятор на экране



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



Рисунок 6.11. Список элементов созданный классом List


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

 


Класс Alert



6.3. Класс Alert



Использование класса Alert в Java 2 ME приложениях обусловлено возникновением различных внештатных ситуаций. В основном класс Alert применяется для создания экрана, который информирует пользователя об ошибке произошедшей в приложении или любом другом уведомлении информационного характера. Экран, определенный классом Alert может содержать строковое уведомление о произошедшей ошибке либо текстовую строку с заданным изображением. В связи с этим, класс Alert имеет два конструктора, использующихся в создании объектов этого класса. Первый конструктор содержит один параметр типа String, задавая строку текста для уведомления. Рассмотрим первый конструктор класса Alert.

public Alert(String  title);

Параметры конструктора public Alert:

 title - строка текста.


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

public Alert(String  title, String alertText, Image  alertlmage, AlertType alertType)

Параметры конструктора public Alert:

 title - название созданного экрана;  alertText - текст уведомления;  alertlmage - изображение;  alertType - тип уведомления, определяемый классом AlertType.


Существует пять типов уведомлений:

 static AlertType ALARM - тревога;  static AlertType CONFIRMATION - предупреждение о возможном действии, которое пользователь должен произвести;  static AlertType ERROR - ошибка;  static AlertType INFO — информационное сообщение;  static AlertType WARNING - предупреждение.


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

 



Класс Font



6.7. Класс Font



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



Класс Form



6.1. Класс Form



Основным экранным классом примеров из главы 5 служил экран, представленный классом Form. Как вы понимаете это не обязательное условие, но я выбрал класс Form не случайно. Дело в том, что реализация класса Form выполнена в виде контейнера, позволяющего встраивать в себя различные компоненты пользовательского интерфейса. Это, пожалуй, единственный и самый мощный по своим возможностям класс. Само по себе название Form подразумевает создание некой формы для заполнения экрана телефона. В предыдущих примерах мы использовали,- так называемую, пустую форму этого класса в виде чистого экрана. Впоследствии, при упоминании термина форма, будет подразумеваться экран телефона, представленный объектом класса Form для интеграции классов пользовательского интерфейса.

Класс Form имеет два конструктора, необходимых при создании объекта этого класса. Первым конструктором мы уже пользовались, и выглядит он достаточно просто:

public Form (String title)

Параметры конструктора класса Form:

 title — заголовок появляется в верхней части созданного окна.


Второй конструктор класса Form имеет уже два параметра, и позволяет встроить компоненты интерфейса в пустую форму, public Form (String title, Item[] items)

Параметры конструктора класса Form:

 title - заголовок окна;  items - массив компонентов размещаемых в классе Form.


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

 



Класс Image



6.6. Класс Image



При рассмотрении класса ImageItem мы уже использовали объекты класса Image, но тогда был рассмотрен только один метод и способ работы с классом Image. В этом разделе вы более подробно познакомитесь с этим классом. Класс Image необходим для загрузки и хранения изображений в формате PNG. Чаще всего загружаемые изображения находятся в рабочем каталоге приложения. Но могут находиться и где угодно, надо только правильно указать путь местонахождения для загрузки. При упаковке приложения в JAR-файл, все имеющиеся изображения автоматически копируются в архив, и при работе программы на телефоне, загрузка уже осуществляется из JAR-файла. Загружаемые изображения могут использоваться во время работы с классами Alert, Choice, ChoiceGroup, Form, ImageItem и Graphics. Качество воспроизведения изображения на экране всецело зависит от возможностей используемого телефона. Если изображение больше фактического размера дисплея, то сервис телефона организует прокрутку изображения и если это не входит в ваши планы, то следует придерживаться минимальных размеров ширины и высоты при создании изображений.

 


Класс Item



6.2. Класс Item



Абстрактный суперкласс Item имеет иерархию из восьми подклассов. Каждый подкласс представляет один из элементов пользовательского интерфейса, например, класс Text Field, создает текстовые поля для ввода пароля, адреса электронной почты или просто числовых значений. Все восемь классов, по сути, устанавливают компоненты пользовательского интерфейса, которые встраиваются в форму определенную классом Form. На рис 6.2 изображена иерархия абстрактного суперкласса Item.



Класс List



6.4. Класс List



Класс List не входит в иерархию класса Item. Использование класса List дает возможность создавать выбираемый список элементов, отображаемый на экране в виде одной или нескольких строк текста. Класс List наследуется от класса Screen и реализует возможности интерфейса Choice. При создании выбираемого списка элементов необходимо указать тип создаваемого списка. Существует всего три типа списков, реализация которых основана на использовании интерфейса Choiсе:

 EXCLUSIVE-предоставляет эксклюзивный выбор элемента в списке;  MULTIPLE - множественный выбор элементов из списка;  IMPLICIT - выбирает из списка только один элемент, на котором сфокусировал свое внимание пользователь.


Конструкция применения типов EXCLUSIVE и MULTIPLE напоминает использование этих типов в классе ChoiceGroup, а вот применение типа IMPLICIT возможно только с использованием класса List. При создании объекта класса List можно воспользоваться двумя видами конструкторов. Рассмотрим их более подробно.

public List(String title, int listType);

Параметры конструктора List:

 title- название создаваемого списка элементов;  listType - тип создаваемого списка, может быть одним из трех значений: IMPLICIT, EXCLUSIVE И MULTIPLE.


Этот конструктор с двумя параметрами создает пустой список с заданным типом в параметре listType. Второй конструктор класса List несколько сложнее. Он состоит из четырех параметров и создает многострочный список элементов с загрузкой иконки или изображения для каждого элемента.

public List(String title, int listType, String[] stringElements, Image[] imageElements)

Параметры конструктора List:

 title - название создаваемого списка элементов;  listType - может быть одним из трех значений IMPLICIT, EXCLUSIVE и MULTIPLE для определения типа создаваемого списка элементов;  stringElements - в этом параметре используется массив строк для создания списка элементов;  imageElements - с помощью этого параметра каждому из элементов можно загрузить свое изображение, чаще всего используются иконки маленьких размеров, например 10 на 10 пикселей.

 


Класс Ticker



6.5. Класс Ticker



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

Класс Ticker имеет один конструктор, необходимый в создании объекта этого класса, рассмотрим этот конструктор:

public Ticker(String  str);

Параметры конструктора класса Ticker:

 str - строка текста появляющаяся в виде бегущей строки.


Создавая объекта класса Ticker с помощью рассмотренного конструктора, вы задаете значение для параметра str и эта строка текста будет циклично прокручиваться в программе.



Класс ChoiceGroup



Листинг 6.1 Класс ChoiceGroup

*/ import javax.microedition.midlet.*; import javax.microedition.Icdui.*; public class MainClassChoiceGroup extends MIDlet implements CommandListener { // команда выхода, из приложения private Command exitMidlet = new Command("Выход", Command.EXIT, 0);
// команда выбора элемента группы  private Command vibor = new Command("Выбрать", Command.SCREEN, 1);
// команда возврата в главное окно private Command vozvrat = new Command("Назад"; Command.BACK, 0);
// объект класса ChoiceGroup private ChoiceGroup groupPopup; // объект класса Form private Form myform; // объект mydisplay представляет экран телефона private Display .mydisplay; public MainClassChoiceGroup()  { mydisplay = Display.getDisplayfthis);
 } // текст для элементов группы private String[] mygroup = {"Флаг 0","Флаг 1","Флаг 2" "Флаг 3"}; public void startApp() { // инициализируем объект groupPopup groupPopup = new ChoiceGroup ("Группа Popup", ChoiceGroup.POPUP,mygroup,null) ; // создаем форму при помощи объекта Form myform = new Form(«Встроенный ChoiceGroup «) ; // добавляем группу элементов myform.append(groupPopup);
 myform.addCoInmand(exitMidlet) ; myform.addCommand(vibor);
myform.setCommandListener(this);
// отражаем текущий дисплей mydisplay.setCurrent(myform);
} public void pauseAppf) {} public void destroyApp(boolean unconditional) {} public void commandAction(Command с, Displayable d) { // выход из приложения  if(с == exitMidlet) { destroyApp(false) ; notifyDestroyed() ; } // возврат в myform if(с == vozvrat) { mydisplay.setCurrent(myform);
 } // обработка выбранного элемента в группе if(с == vibor) { int i = groupPopup.getSelectedlndex();
if(i ==0) { Form formPopup = new Form("Это formPopup"+mygroup[0]);
formPopup.append(mygroup[0]);
formPopup.addCommand(vozvrat);
formPopup.addCommand(exitMidlet);
formPopup.setCorranandListener(this);
mydisplay.setCurrent(formPopup);
} if(i = = 1){ Form formPopup = new Form("Это formPopup"+mygroup[1]);
formPopup.addCommand(vozvrat);
formPopup.append(mygroup[1]);
formPopup.addCommand(exitMidlet);
formPopup.setCommandListener(this);
mydi splay.setCurrent(formPopup);
} if(i == 2) { Form formPopup = new Form("Это formPopup"+ mygroup[2]);
formPopup.append(mygroup[2]);
formPopup.addCommand(vozvrat);
formPopup.addCommand(exitMidlet);
formPopup.setCommandListener(this);
mydisplay.setCurrent(formPopup);
} if(i = = 3) { Form formPopup = new Form("Это formPopup"+mygroup[ 3 ] ) ; formPopup.append(mygroup[3]);
formPopup.addCommand(vozvrat);
formPopup.addCommandtexitMidlet);
formPopup.setCommandListener(this) ; mydisplay.setCurrent(formPopup);
} }  } }

Вся программа основывается на классе MainClassChoiceGrop. К команде выхода exitMidlet добавлены еще две команды обработки событий - это vozvrat и vibor. Команда vozvrat возвращает,пользователя обратно в главное окно приложения, в которое он попадает при запуске программы. С помощью команды vibor, происходит выбор заданных действий, то есть отклик программы на выбранный элемент группы. Как мы уже договорились, каждый элемент группы POPUP (всего их будет четыре), должен привести пользователя в свой экран, установленный с помощью класса Form. Далее в листинге 6.1 идет объявление необходимых объектов для классов Form, ChoiceGrop и Display. После конструктора идет строка кода создающая текст для элементов группы:

private String[] mygroup = {"Флаг 0","Флаг'1","Флаг2","Флаг3"};

С помощью переменной mygroup создается массив текстовых данных для инициализации всей группы элементов. После создания переменной mygroup следует код метода startApp (). Первой строкой кода в методе startApp () инициализируется объект groupPopup класса ChoiceGroup. Конструктор этого класса мы подробно уже рассматривали, но небольших пояснений требуют два последних параметра. Оба параметра могут быть представлены в виде массива данных. Предпоследний параметр конструктора класса ChoiceGroup, инициализирующий объект mygroup, создает четыре строки текста в виде выпадающего меню (поскольку мы использовали значение POPUP во втором параметре конструктора класса ChoiceGroup). Все четыре строки текста и есть группа элементов, дающая пользователю выбор конкретных действий. Последний параметр в конструкторе класса ChoiceGroup служит для загрузки каждому элементу группы своего изображения или иконки, которая будет отображаться слева от" текста, назначенного для каждого элемента группы. Поскольку изображения вы еще загружать не умеете (чему мы, безусловно, научимся), то надо выставить это значение в null. После инициализации объекта groupPopup создается форма на основе класса Form, добавляются команды выхода и выбора, и самое главное, происходит встраивание объекта groupPopup класса ChoiceGroup в форму класса Form. После чего текущий экран дисплея отображается посредством строки кода:

mydisplay.setCurrent,(myform) ;

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

После того, как произведен выбор элемента группы и нажата клавиша с командой Выбор, программа попадает в обработчик событий этой команды, назначенный для переменной vibor. Далее используется метод getSelectedIndex() класса ChoiceGroup, с помощью которого происходит получение индекса выбранного элемента группы и помещение результата в переменную i. После чего происходит сравнение полученного индекса с четырьмя значениями, заданными для каждого элемента. Соответственно, после совпадения индекса и значения выбранного элемента, происходят действия заданные для этого выбора. В примере происходит создание нового экрана с информационной надписью о выбранном элементе группы, добавлением команд выхода из приложения и возврата в главное окно программы. В этой программе, в ответ на действия по выбору элемента группы, создается новый экран с объектом класса Form. В ваших программах это могут быть любые другие события, необходимые для решения конкретных задач.
 


Класс DateField



Листинг 6.2 Класс DateField .

*/ import javax.microedition.midlet.*;  import javax.microedition.Icdui.*; public  class     MainClassDateField extends MIDlet   implements CoramandListener { // команда выхода из приложения private Command exitMidlet = new Command(«Выход», Command.EXIT, 0);
// объект класса DateField private DateField dt; // объект класса Form private Form myform;. // объект mydisplay представляет экран телефона private Display mydisplay; public MainClassDateField() { mydisplay = Display.getDisplay(this);
} public void startApp() { //инициализируем объект dt dt = new DateField("Дата и Время", DateField.DATE_TIME);
// создаем форму при помощи объекта Form myform = new Form("Встроенный DateField");
// добавить объект dt myform,append(dt);
myform.addCommand(exitMidlet);
myform.setCommandListener(this);
// отразить текущий дисплей mydisplay.setCurrent(myform);
} public void pauseApp() {} public void destroyApp(boolean unconditional) {} public void commandAction(Command c, Displayable d) { // выход из приложения if(с = = exitMidlet)      { destroyApp(false) , notifyDestroyed();
 } }  }  }

В примере создан класс MainClassDateField, соответствующий названию разбираемого класса. Сам по себе пример очень легкий в силу простоты реализации самого класса DateField. Первоначально создается объект dt для класса DateField, после этого происходит его инициализация в методе startАрр (). Создается форма классом Form и объект dt интегрируется в эту форму. Все остальное, а именно: циферблат и календарь, показанные на Рисунок 6.4, создаются автоматически с помощью эмулятора телефона при выборе одного из элементов класса. В нашем примере был создан объект dt класса DateField, но можно было этого и не делать, а обойтись, например такой простой записью:

Form f = new.Form(new DateField("Дата и Время", DateField.DATE_TIME);


Такая запись используется иногда в профессиональных программах, где это действительно очевидно и не затруднит чтения и понимания всей программы в целом.

После того, как вы откомпилируете этот пример и запустите приложение, на экране появятся два элемента с надписями time и date. Выбрав один из элементов и нажав на кнопку Select, вы попадете, в зависимости от выбора, на экран с календарем или временем, изображенным на Рисунок 6.4. С помощью джойстика или клавиш перемещения, можно установить необходимые параметры для обоих элементов.
 


Класс TextField



Листинг 6.3 Класс TextField

*/ import javax.microedition.midlet.*; -import javax.microedition.Icdui.*; public class MainClassTextField extends MIDlet implements CommandListenef { // команда выхода -из приложения private Command exitMidlet = new Command("Выход",Command.EXIT, 0) ; // объект класса Form private Form myform; // объект mydigplay представляет экран телефона private Display mydisplay; public MainClassTextFieldf) { mydisplay = Display.getDisplay(this);
} public void startApp() {                                                                       // создаем форму при помощи объекта Form myform = new Form("Класс TextField");
 // добавить в форму поле для текста myform.append(new TextField( "Введите текст:","",20,TextField.ANY));
// добавить в форму поле для пароля myform.append(new TextField( "Введите пароль:","",20,TextField.PASSWORD));
 // добавить в форму поле для e-mail myform.append(new TextField( "Введите E-mail:","",20,TextField.EMAILADDR));
// добавить в форму поле для URL myform.append(new TextField( "Введите URL:","",20,TextField.URL));
// добавить в форму поле для телефонного номера myform.append(new TextField( "Телефонный номер:","",20,TextField.PHONENUMBER));
 myform.addCommand(exitMidlet);
myform.setCommandListener(this);
mydisplay.setCurrent(myform);
} public void pauseApp() {} public void destroyApp(boolean unconditional) {} public void commandAction(Command c, Displayable d) { //   выход  из  приложения  if(с  = =  exitMidlet)  { destroyApp(false);
notifyDestroyed() ; } }  }

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

myform.append(new TextField ("Введите текст:","",20,TextField.ANY));


Здесь используется упрощенная запись без создания объект класса TextField. Первый параметр конструктора TextField задает информационную строку текста - метку, поясняющую назначение данного текстового поля. В следующий параметр конструктора класса TextField, а точнее в переменную, отвечающую за текстовый массив данных, пользователь будет вводить необходимую информацию. Значение этого параметра пустое, но возможно поместить любой текст, который в последствии можно редактировать. Числовое значение 20 задает длину или количество введенных символов. Последний параметр использует константу ANY, дающую возможность вводить любую комбинацию символов и цифр.

Все созданные поля в листинге 6.3 используют, рассмотренную выше конструкцию программного кода и только в последнем параметре конструктора TextField, значение варьируется для пароля, e-mail, веб-сайта и телефонного номера. Задавая различные значения последнему параметру при создании объекта этого класса, вы можете создать набор необходимых полей. На Рисунок 6.5 изображен эмулятор, показывающий несколько полей класса TextField.

Класс Stringltem



Листинг 6.4 Класс Stringltem

*/ import javax.microedition.midlet.*;  import javax.microedition.Icdui.*; public class MainClassStringltem extends MIDlet implements CommandListener, ItemCommandListener { // команда выхода из приложения private Command exitMidlet = new Command("Выход", Command.EXIT, 0);
// команда перехода по нажатию кнопки private Command perexodButton = new Command("Дальше",Command.ITEM, 1);
 // команда перехода по гиперссылке private Command perexodHyperlink = new Command("Перейти", Command.ITEM, 1);
// команда возврата в основное окно private Command vozvrat = new Command("Назад", Command.BACK, 1);
// объект класса Form private Form myform, // объект mydisplay представляет экран телефона private Display mydisplay; public void startApp() { mydisplay = Display.getDisplay (this) ; myform = new Form("Класс Stringltem");
Stringltem si = new Stringltem("Метку", "Текст");
myform.append(si);
// создать гиперссылку Stringltem s2 = new Stringltem("Гиперссылка", "www.dmk.ru",Item.HYPERLINK);
s2.setDefaultCommand(perexodHyperlink);
s2.setltemCommandListener(this);
myform.append(s2);
// создать текст в виде кнопки Stringltem s3 = new Stringltem("Кнопка","Опции",Item.BUTTON);
s3.setDefaultCommand(perexodButton);
s3.setltemCommandListener(this);
 myform.append(s3);
myform.addCommand(exitMidlet);
myform.setCommandListener(this);
mydisplay.setCurrent(myform);
 } protected void destroyApp(boolean unconditional) {} protected void pauseAppO {} // обработчик класса ItemCommandListener public void commandAction(Command c, Item i) { // переход в окно опций if (с = = perexodButton)  { Form f1 = new Form("Опции");
f1.append("Необходимые Опции");
f1.addCommand(exitMidlet) ; f1.addCommand(vozvrat);
f1.setCommandListener(this) ; mydisplay.setCurrent(f1) ; } // переход по гиперссылке  if (c = = perexodHyperlink) { Form f2 = new Form("Издательство ДМК");
f2.append("Сайт издательства ДМК");
f2.addCommand(exitMidlet);
f2.addCommand(vozvrat);
f2.setCommandListener(this);
mydisplay.setCurrent(f2);
}  } public void commandAction(Command c, Displayable d) { // выход из приложения if(с == exitMidlet) { destroyApp(false);
notifyDestroyed();
} //   возврат  в основную форму if(с  = = vozvrat)   mydisplay.setCurrent(myform);
} }

В коде листинга 6.4 для наглядности не использовался конструктор основного класса мидлета MainClassStringltem, но добавлялся, как уже упоминалось новый интерфейс ItemCommandListener для установки обработки команд перехода в приложении. В методе startApp () происходит создание пустой формы для класса Form и интеграция класса Stringltem. В строке кода:

Stringltem si = new Stringltemf"Метку", "Текст");


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

Stringltem s2 =new Stringltem("Гиперссылка", "www.dmk.ru",Item.HYPERLINK);
s2.setDefaultCommand(perexodHyperlink);
s2.setItemCommandListener(this) ; myform.append(s2) ; Stringltem s3 = new Stringltem("Кнопка","Опции"»,Item.BUTTON);
s3.setDefaultCommand(perexodButton);
s3.setltemCommandListener(this);
myform.append(s3);


формирует текст на экране телефона, назначив для него обработчик событий при помощи метода setltemCommandListener(). Можно получить текст в виде активной ссылки. При создании объекта s2 класса Stringltem использовался конструктор с тремя параметрами. Последний параметр этого конструктора как раз и отвечает за вид создаваемой ссылки. Была создана гиперссылка с помощью константы HYPERLINK. Блоком кода с объектом s3 уже создавалась кнопка. Эта кнопка является так же простым статическим текстом, но оформленным в виде прямоугольной кнопки. Объекту s3 так же назначается обработчик событий методом setltemCommandListener (), благодаря чему и получается активная ссылка. Выбрав ее можно перейти в нужное место в приложении.

Теперь наша программа имеет два одноименных обработчика событий с разными параметрами, представленными двумя интерфейсами CommandListener и ItemCommandListener. Обработчик событий созданный при помощи метода commandAction (Command с, Item i), следит за двумя активными ссылками, выполненными в виде гиперссылки и кнопки. Выбрав одну из активных ссылок и воспользовавшись соответственной командой перехода perexodButton - для кнопки и реrexodHyperlink, вы попадете на экран с новой формой и информационной надписью. Оба новых экрана созданы классом Form, где так же имеются две команды: exitMidlet -для выхода из приложения и vozvrat — для возврата в основное окно. Эти две команды обрабатываются своим методом commandAction(Command с, Displayable d) интерфейса CommandListener. Для того, чтобы создать активную ссылку, необходимо воспользоваться интерфейсом ItemCommandListener, реализовав метод commandAction () для обработки необходимых событий.

public class MainClassSpacer extends MIDlet



Листинг  6.5

Класс Spacer */ import javax.microedition.midlet.*; import javax.microedition.Icdui.*; public class MainClassSpacer extends MIDlet implements CorranandListener { // команда выхода из приложения private Command exitMidlet = new Command("Выход", Command.EXIT, 0);
// объект класса DateField private Spacer sp; // объект класса Form private Form myform; // объект mydisplay представляет экран телефона private Display mydisplay; public MainClassSpacer() { mydisplay = Display.getDisplay(this);
}  public void startApp()  { // инициализируем объект sp sp = new Spacer(50,0);
// создаем форму при помощи объекта Form myform = new Form("Класс Spacer");
// добавить объект sp myform.append(sp);
myform.append(new TextField("Метку","Текст",20,TextField.ANY));
myform.addCommand(exitMidlet);
myform.setCommandListener(this);
// отразить текущий дисплей mydisplay.setCurrent(myform);
} public void pauseApp() {} public void destroyApp(boolean unconditional) {} public void commandAction(Command c, Displayable d) { //   выход из  приложения if(с  = = exitMidlet) { destroyApp(false);
notifyDestroyed();
 }  }  }

В листинге 6.5 создается рабочий класс MainClassSpacer и форма на основе класса Form. Объявляется объект sp для класса Spacer и инициализируется в методе startApp (). При инициализации объекта sp используются два значения для параметров, создавая тем самым пустое пространство с левой стороны от текстового поля, созданного при помощи класса TextField. Эмулятор изображенный на Рисунок 6.7 показывает работу программы из листинга 6.5.

Класс Spacer был добавлен в Java 2 ME для профиля MIDP 2.0, нельзя сказать, что этот элемент жизненно необходим, но бывают случаи, когда использование класса Spacer облегчает работу программиста.

Класс Imageltem */



Пример достаточно прост: происходит загрузка изображения на экран телефона представленного классом Form с добавлением команды выхода из приложения. Но после компиляции листинга 6.6 и запуска приложения на эмуляторе J2ME Wireless Toolkit 2.1, возникают цветовые дефекты в виде некачественного отображения фотографии. Это вызвано, прежде всего, минимальной цветовой гаммой, представляемой эмулятором J2ME Wireless Toolkit 2.1. Протестируйте код из листинга 6.6 на различных эмуляторах, рассмотренных в главе 4. На рис 6.8 показан эмулятор с изображением на экране фотографии.

 


Класс Gauge



Листинг 6.7 Класс Gauge

*/import javax.microedition.midlet.*;  import javax.microedition.Icdui.*; public class MainClassGauge extends MIDlet implements CommandListener { // команда выхода из приложения private Command exitMidlet = new Command!"Выход", Command.EXIT, 1);
// объект класса Form private Form myform = new Form("Класс Gauge");
// объект mydisplay представляет экран телефона private Display mydisplay; public MainClassGauge() { mydisplay = Display.getDisplay(this) ; } public void startApp() { // добавить объект класса Gauge myform.append(new Gauge("Прогресс:", true, 10, 5 ));
// установка обработчика событий для Form myform.addCommand(exitMidlet);
myform.setCommandListener(this);
// отразить текущий дисплей mydisplay.setCurrent(myform);
} public void pauseApp() {} public void destroyApp(boolean unconditional) {} public void commandAction(Command c, Displayable d) { // выход из приложения if (с = = exitMidlet) { destroyApp(false);
notifyDestroyed();
}  } }

Откомпилировав этот пример, вы увидите на экране прямоугольник, наполовину закрашенный темным цветом. Использование класса Gauge позволяет создавать экранные заставки отображающие, например, процесс загрузки Приложения. Для того чтобы пользователь не наблюдал за черным экраном телефона в момент загрузки очередного процесса, создайте класс Gauge и используйте его по назначению.
 


public class MainClassAlert extends MIDlet



Листинг 6.8

Класс Alert */ import javax.microedition.midlet.*;  import javax.microedition.Icdui.*; public class MainClassAlert extends MIDlet implements CommandListener { // команда выхода из приложения private Command exitMidlet = new Command("Выход", Command.EXIT, 1);
// объект класса Alert Alert a1; // объект mydisplay представляет экран телефона private Display mydisplay; public MainClassAlert() { mydisplay = Display.getDisplay(this);
} public void startApp() { // перехватываем исключительную ситуацию try{ // загрузка изображения Image image = Image.createlmage("/error.png");
// объект класса Alert a1 = new Alert("Класс Alert",null, image, AlertType.ERROR);
} catch(Java.io.IOException ex){ } al.addCommand(exitMidlet);
al.setCommandListener(this);
mydisplay.setCurrent(al);
 } public void pauseApp() {} public void destroyApp(boolean.unconditional) {} public void commandAction(Command c, Displayable d) { // выход из приложения if (с == exitMidlet) { destroyApp(false) ; notifyDestroyed() ; }  }  }

В листинге 6.8 создается класс MainClassAlert, являющийся основным классом мидлета. В самом начале всего кода происходит объявление необходимых переменных ив частности объекта a1 класса Alert. В методе startApp () создается объект класса Image, в котором будет содержаться загружаемое изображение. Изображение выполнено в виде информационной надписи об ошибке. На Рисунок 6.10 изображена работа класса Alert.

При загрузке изображения используется конструкция try {} catch () {} для обработки исключительных ситуаций. В остальном, я думаю, весь код ясен и каких-либо проблем с пониманием этой простой программы возникнуть не должно.

public class MainClassList extends MIDlet



Листинг 6.9

Класс List */ import javax.microedition.midlet. *;  import javax.microedition.Icdui.*; public class MainClassList extends MIDlet implements . CommandListener { // команда выхода из приложения private Command exitMidlet = new Command("Выход", Command.EXIT, 0);
// команда выбора элемента из списка private Command vibor = new Command!"Выбор", Command.SCREEN, 1);
// команда возврата в главное окно private Command vozvrat = new Command("Назад", Command.BACK, 1}; // команда выбора элемента для типов Implicit и Multiple private Command OK = new Command("OK", Command.OK, 1);
// массив, иконок для типа EXCLUSIVE Image[] iconEx = null; // массив иконок для типа Multiple Image t ] iconMu = null; // массив иконок для типа Implicit Image[] iconlm = null; // объект класса List для типа EXCLUSIVE private List mylistEx; // объект класса List для типа Multiple private List mylistMu; // объект класса List для типа Implicit private List mylistlm; // объект mydisplay представляет экран телефона private Display mydisplay; public MainClassList() { mydisplay = Display.getDisplay(this);
} public void startAppf)  {  // перехватываем.исключительную ситуацию; try { // загрузка изображения Image imagel = Image.createlmage("/iconMu.png");
Image image2 = Image.createlmage("/iconlm.png");
// поместить загруженные изображения в массив iconEx iconEx = new Image[] { image1, image2 }; // загрузка изображения Image imageB = Image.createlmage("/Multiple.png");
// поместить загруженные изображения в массив iconMu iconMu = new Image[]{image3, image3, image3, image3}; // загрузка изображения Image image4 = Image.createlmage("/Implicit.png");
// поместить загруженные изображения в массив iconIm iconIm = new Image[]{image4, image4, image4}; } catch(Java.io.IOException ex){ } // текст для двух элементов списка String[] st = {"Тип Multiple","Тип Implicit"}; // инициализация объекта mylistEx mylistEx = new List("Тип EXCLUSIVE", Choice.EXCLUSIVE, st, iconEx);
// добавить команды  mylistEx.addCommand(exitMidlet);
 mylistEx.addCommand(vibor);
mylistEx.setCommandListener(this);
// отразить текущий дисплей mydisplay.setCurrent(mylistEx);
} public void pauseApp() {} public void destroyApp(boolean unconditional) {} public void commandAction(Command c, Displayable d)  { // выход из приложения  if(с == exitMidlet) { destroyApp(false);
notifyDestroyedf);
} // возврат в главное окно  if(с = = vozvrat) Display.getDisplay(this).setCurrent(mylistEx);
 // обработка команды OK if(с = = OK) { Alert a1 = new Alert(null,"Информационное уведомление", null, null);
mydisplay.setCurrent(al);
 } // обработка команды vibor if(с == vibor) { // взять индекс выбранного элемента int i = mylistEx.getSelectedlndex();
// события для элемента «Тип Multiple» if(i = =0) { // текст для элементов списка String[] string = {"Меч","Щит","Нож","Копье"}; // инициализация объекта mylistMu mylistMu = new List("Тип MULTIPLE", Choice.MULTIPLE, string, iconMu);
// добавить команду возврата mylistMu.addCommand(vozvrat);
// добавить команду OK mylistMu.addCommand(OK);
mylistMu.setCommandListener(this);
// отразить текущий дисплей mydisplay. setCurrent (mylistMu) } // события для элемента «Тип Implicit» if (i = = 1) { // текст для элементов списка String[] string = {"Звук","Видео","Управление"}; // инициализация объекта mylistlm mylistlm = new List("Тип IMPLICIT", Choice.IMPLICIT, string, iconlm);
// добавить команду возврата mylistlm.addCommand(vozvrat);
// добавить команду OK mylistlm.addCommand(OK);
mylistlm. setCommandListener (this);
// отразить текущий дисплей mydisplay.setCurrent(mylistlm);
} }  }  }

В листинге 6.9 создан класс MainClassList, являющийся основным классом мидлета программы. В начале исходного кода создаются команды для выхода из приложения - exitMidlet, для выбора элемента из списка - vibor, для возврата в главное окно приложения - vozvrat и команда ОК, обрабатывающая выбранный элемент из группы. За командами обработки событий следует объявление трех переменных: iconEx, iconMu и iconIm. Все три переменные будут содержать массив изображений или иконок для трех рассматриваемых в этом примере типов Exclusive, Multiple и Implicit класса List. Затем в коде:

private List mylistEx; private List mylistMu; private  List  mylistlm; private Display mydisplay;

Создаются три объекта класса List, представляющие три имеющихся типа элементов списка и объект mydisplay класса Display. Метод startApp() производит загрузку всех имеющихся иконок из папки \Code\Listing6_9\res с помощью метода createImage класса Image. Все загруженные иконки содержатся в переменных image1, image2, image3 и image4. При загрузке изображений используется конструкция try{} catch {) {} для перехвата исключительной ситуации. Все иконки размещаются в массивах iconEx, iconMu и iconIm для каждого типа элементов списка. В сроке кода

mylistEx = new List("Тип EXCLUSIVE", Choice.EXCLUSIVE, st, iconEx)

происходит инициализация объекта mylistEx. Используется конструктор класса из четырех параметров. Первый параметр конструктора класса List создает заголовок для всего экрана. Во втором параметре конструктора используется значение Choice.EXCLUSIVE. С помощью этого значения создается список элементов типа Exclusive, позволяющий выбрать только один элемент из всего списка. Третий параметр в конструкторе класса List принимает значение переменной st. Эта переменная содержит две строки текста, создавая тем самым только два элемента списка. Последний параметр загружает две иконки для обоих элементов списка.

В методе commandAction () происходит обработка всех .имеющихся команд созданных в приложении. Команда exitMidlet производит выход из приложения. Команда vozvrat возвращает пользователя в главное окно программы. Команда ОК показывает информационное сообщение, выполненное на основе класса Alert. Команда vibor осуществляет переход в выбранный экран представленный списком элементов двух различных типов Multiple и Implicit класса List. С помощью метода getSelectedIndex() берется индекс выбранного элемента из списка и на его основе в конструкции if /else происходит обработка выбранных событий. Два типа списков Multiple и Implicit создаются подобно списку типа Exclusive.

public class MainClassTicker extends MIDlet



Листинг 6.10

Класс Ticker */ import javax.microedition.midlet*;  import javax.microedition.Icdui*; public class MainClassTicker extends MIDlet implements CommandListener { // команда выхода из приложения private Command exitMidlet = new Command("Выход", Command.EXIT, 0);
// объект класса Form private Form myform; // объект mydisplay представляет экран телефона private Display mydisplay; public MainClassTicker() { mydisplay = Display.getDisplay(this);
} public void startApp()  { // создаем форму при помощи объекта Form myform = new Form("Класс Ticker");
// создаем объект класса Ticker Ticker myticker = new Ticker("Бегущая строка");
// добавляем бегущую строку в форму myform.setTicker(myticker);
// добавить команду выхода myform.addCommand(exitMidlet);
myform.setCommandListener(this);
mydisplay.setCurrent(myform);
} public void pauseApp() {} public void destroyApp(boolean unconditional) {} public void commandAction(Command c, Displayable d)  { // выход из приложения if(с  ==  exitMidlet) { destroyApp(false);
notifyDestroyed() ; }  } }

В листинге 6.10 создается пустая форма с помощью класса Form и объект класса Ticker с заданным текстом. Методом setTicker (), объект класса Ticker добавляется в форму, организовывая тем самым бегущую строку в верхней части экрана телефона.
 


MainClassImage extends MIDlet implements CommandListener



Листинг 6.11

Класс Image  */ import javax.microedition.midlet.*;  import javax.microedition.Icdui.*; public class  MainClassImage extends MIDlet implements CommandListener  { // команда выхода из приложения private Command exitMidlet = new Command("Выход", Command.EXIT, 1) ; // объект класса Form, private Form myform = new Form("Класс Image");
// объект mydisplay представляет экран телефона private Display mydisplay; public MainClassImage()        { mydisplay = Display.getDisplay(this);
 } public void startApp() { // перехватываем исключительную ситуацию try { // загрузка изображения Image im = Image.createlmage("Ygornakov.png");
// добавляем загружённый файл в форму myform.append(im);
} catch(Java.io.IOException exp{ } // Установка обработчика событий для Form myform.addCommand(exitMidlet);
myform.setCommandListener(this);
// Отразить текущий дисплей mydisplay .s'etCurrent (myform) ;  } public void pauseApp() {} public void destroyApp(boolean unconditional) {} public void сommandAction(Command c, Displayable*d) { // Выход из приложения if (с == exitMidlet)  { destroyApp(false);
notifyDestroyedf);
 } } }

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


команда выхода из приложения private



Листинг   6.12

Класс  Font */  import   javax.microedition.midlet. *; import* javax.microedition.Icdui.*; public  class    MainClassFont  extends MIDlet  implements CommandListener { // команда выхода из приложения private Command exitMidlet = new Command("Выход", Command.EXIT, 0);
// массив иконок Image[] icon = null; x // объект класса List private List mylist; // объект mydisplay представляет экран телефона private Display mydisplay; public MainClassFont() { mydisplay = Display.getDisplay(this);
} public void startApp() { // перехватываем исключительную ситуацию try{ // загрузка изображения Image imaged = Image.createlmage("/icon0.png");
Image imagel = Image.createlmage("/icon1.png");
Image image2 = Image.createlmage("/icon2.png");
Image image3 = Image.createlmage("/icon3.png");
// поместить загруженные изображения в массив icon icon = new Image[]{ image0, image1, image2, image3}; } catch(Java.io.IOException ex){ } // текст для четырех элементов списка String[] stroka = {"Синий","Красный","Зеленый", "Оранжевый"}; // назначается шрифт нулевому элементу списка Font f0 = Font.getFont(Font.FACE_PROP6RTIONAL, Font.STYLE_PLAIN, Font.SIZE_SMALL);
// назначается шрифт первому элементу списка Font f1 = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_BOLD,Font.SIZE_MEDIUM);
// назначается шрифт второму элементу списка Font f2 = Font.getFont(Font.FACE_MONOSPACE, Font.STYLE_ITALIC,Font.SIZE_LARGE);
// назначается шрифт третьему элементу списка Font f3 = Font.getFont(Font.FACE_SYSTEM, Font.STYLEJJNDERLINED, Font.SIZE_LARGE);
// инициализация объекта mylist mylist = new List("Класс List", Choice.EXCLUSIVE, stroka, icon);
// устанавливается шрифт нулевому элементу списка mylist. setFont (0 , f0), ; // устанавливается шрифт первому элементу списка mylist.setFont(I,f1);
// устанавливается шрифт второму элементу списка mylist .setFont.(2 , f 2) ; //устанавливается шрифт третьему элементу списка mylist.setFont(3,f3);
// добавить команду выхода mylist.addCommand(exitMidlet);
mylist.setCommandListener(this);
 // отразить текущий дисплей mydisplay.setCurrent(mylist);
} public void pauseApp() {} public void destroyApp(boolean unconditional) {} public void commandAction(Command c, Displayable d) {// выход из приложения if(с == exitMidlet) {destroyАрр(false);
notifyDestroyed() ; } } }

Основным классом в программе из листинга 6.13, иллюстрирующей работу со шрифтом, является класс MainClassFont. Весь код программы построен на использовании класса List создающем список элементов. В строке кода:

Image[]  icon =  null

создается переменная для хранения массива изображений. Конкретно в этом примере будут использованы маленькие иконки, загружаемые каждому элементу списка. Всю группу элементов представляет объект my list класса List. В методе startApp () происходят основные действия по созданию списка элементов, загрузке изображения и назначению шрифта каждом элементу списка. В четырех строках кода:

Image imaged = Image.createlmage("/icond.png");
Image imagel = Image.createlmage("/iconl.png");
Image image2 = Image.createlmage("/icon2.png");
Image image3 = Image.createlmage("/iconS.png");


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

icon = new Image[]{imaged, image1, image2, image3};

Далее в программном коде создается массив строковых значений:

String[] stroka = {"Синий","Красный","Зеленый","Оранжевый"}.

Теперь пришло время создать шрифты:

Font  f0 = Font.getFontfFont.FACE_PROPORTIONAL, Font.STYLE_PLAIN, Font.SIZE_SMALL);
Font f1 = Font.getFont(Font.FACE_SYSTEM,Font.STYLE_BOLD, Font.SIZE_MEDIUM);
Font f2 = Font.getFont(Font.FACE_MONOSPACE, Font. STYLE_ITALIC, Font. SIZE_LARGE);
  Font f3 = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_UNDERLINED,Font.SIZE_LARGE);


В этих строках создаются четыре переменные f 0...f 3, содержащие различные по стилю, размеру и начертанию шрифты. С помощью созданных переменных впоследствии будет производиться установка шрифтов для каждого элемента списка. Список элементов представлен объектом mylist и выполнен по типу Exclusive (четыре элемента со своими иконками). В классе List имеется метод setFont () доступный в профиле MIDP 2.0, он и используется в примере.

Создав объект класса List, установим шрифт всем элементам списка:

mylist.setFont(0,f0);
mylist.setFont(1,f1);
mylist.setFont(2,f2);
mylist.setFont(3,f3);


С помощью метода setFont () происходит установка заданного шрифта, содержащегося в переменных f 0... f 3. Назначение шрифта происходит по индексам от 0 до 3 в массиве stroka [ ].

В конце кода происходит добавление команды выхода и отображение текущего экрана на дисплее телефона. На Рисунок 6.14 представлена работа программы из листинга 6.13.

Объект класса Ticker создает в



Рисунок 6.12. Объект класса Ticker создает в верхней части экрана бегущую строку


 



Показывает экран эмулятора с несколькими



Рисунок 6.6 показывает экран эмулятора с несколькими элементами класса Stringltem.



Рисунок 6.6. Элементы класса Stringltem

 



Поля класса TextField



Рисунок 6.5. Поля класса TextField


 



Расположение элементов в форме



Рисунок 6.1. Расположение элементов в форме



Все компоненты, встроенные в форму, жестко закреплены и не перемещаются. Редактировать компоненты можно при помощи методов класса Form, причем присоединенные компоненты располагаются друг под другом, выравниваясь горизонтально. Пользователь может перемещаться по компонентам формы с помощью клавиш Вверх и Вниз. Когда количество добавленных компонентов больше видимой части экрана телефона, то автоматически создается прокрутка. Внизу или вверху экрана появляется стрелочка, сигнализирующая об имеющихся компонентах, выпадающих из зоны видимости. При переходе в нижнюю > часть экрана, как только верхний компонент выйдет из зоны видимости, стрелочка автоматически развернется на 180°, указывая в направлений новых компонентов, выпадающих из зоны видимости. Такой механизм реализован в любом телефоне вне зависимости от производителя. Можно добавлять любое количество компонентов в форму, но очевидно, что необходимо задуматься и о дизайне пользовательского интерфейса и не валить все «в кучу». Наилучшим решением будет продуманная структура переходов с экрана на экран.

 


Типы группы элементов ChoiceGroup



Рис 6.3. Типы группы элементов ChoiceGroup



Первый тип группы элементов на рис 6.3, выполнен в виде выпадающего меню и спрограммирован на основе типа POPUP. В данном случае это список из четырех флажков, с помощью которых можно выбрать заданные действия. Четыре флажка в меню были созданы абсолютно произвольно. Количество флажков и как следствие, количество вариантов выбора зависит от задачи поставленной перед программистом. Следующая группа, изображенная на Рисунок 6.3 представлена типом MULTIPLE. В этой группе элементов пользователь имеет возможность многократного выбора, т.е. можно выбрать сразу несколько вариантов. Обычно такая группа элементов используется при настройке различных опций, где возможно указать сразу несколько вариантов выбора. Третья и последняя группа элементов задается типом EXCLUSIVE, и возможен лишь один вариант выбора заданного флажка. Чтобы создать в приложении необходимую группу элементов нужно воспользоваться конструктором класса ChoiceGroup. Всего имеется два конструктора. Первый конструктор с двумя параметрами:

public ChoiceGroup(String label, int choiceType)

Параметры конструктора ChoiceGroup:

label - это строка текста или информационная метка;  choiceType - тип, указывающий на создаваемую группу элементов. Его можно задавать, например, следующим образом: Choice.EXCLUSIVE, Choice .MULTIPLE или Choice. POPUP.


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

public ChoiceGroup(String label, int choiceType, String[] stringElements, Image[] imageElements)

Параметры конструктора ChoiceGroup:

 String — строка текста;  choiceType - тип, указывающий на создаваемую группу элементов;  stringElements - заданный массив текста для каждого элемента группы;  imageElaments - заданный массив изображений для каждого элемента группы.


Два последних параметра конструктора класса ChoiceGroup предназначены для создания массива названий и изображений для элементов группы, например, таким образом:

String[] string = {"Флаг 0","Флаг 1","Флаг 2","Флаг 3"}

Для того чтобы добавить в пустую форму класса Form все три имеющиеся группы элементов, нужно создать три объекта класса ChoiceGroup и воспользоваться методом append () класса Form, например:

ChoiceGroup groupMultiple=new ChoiceGroup("Группа Multiple",ChoiceGroup.MULTIPLE); ChoiceGroup groupPopup=new ChoiceGroup("Группа Popup",ChoiceGroup.POPUP); ChoiceGroup groupExclusive=new ChoiceGroup("Группа Exclusive", ChoiceGroup.EXCLUSIVE); Form myform = new,Form("Встроенный ChoiceGroup"); myform.append(groupPopup); myform.append(groupMultiple); myform.append(groupExclusive);

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

Методы класса ChoiceGroup

Всего имеется семнадцать методов, ознакомимся с основными и наиболее используемыми методами.

 int append (String stringPart, Image imagePart) -добавляет элемент в группу;  void delete (int elementNum) -удаляет заданный элемент из группы;  void deleteAll() - удаляет все элементы;  Font getFont(int elementNum) - получает используемый шрифт элемента группы;  Image getlmage(int elementNum) - получает изображение для элемента группы;  int getSelectedFlags(boolean[]selectedArray_return) -возвращает значение Boolean для группы элементов. Обычно эта функция используется с эксклюзивным типом элементов группы;  int getSelectedlndexl) - возвращает индекс выбранного элемента группы;  void insert(int elementNum,String stringPart,Image imagePart) - вставляет элемент в группу;  boolean isSelected(in't elementNum) - получает выбранную логическую величину.  void set(int elementNum, String stringPart, Image imagePart) - устанавливает текст и изображения в заданный элемент группы, при этом удаляя предыдущую запись;  void setFont(int elementNum, Font font) - устанавливает шрифт заданному элементу;  void setSelectedlndexfint elementNum, boolean selected) -устанавливает особое состояние для элемента группы при использовании множественного типа;  int size ()-возвращает количество используемых элементов группы.


Прежде чем рассматривать практическую часть раздела, давайте разберемся, что именно от нас требуется чтобы воспользоваться компонентами класса ChoiceGroup. Итак, сначала необходимо создать объект класса Form или. пустую форму, куда можно встроить объекты класса ChoiceGroup. Далее необходимо определить, что именно будет происходить при выборе элемента группы. Я предлагаю рассмотреть вариант перехода в новое окно после выбора конкретного элемента группы, где мы выведем простую информационную надпись. Для этого необходимо создать две команды перехода. Одна из команд будет реагировать на выбранный элемент группы, перемещая пользователя в новое окно, а другая команда перехода - возвращать в окно выбора. Пожалуй, это все что от нас 'сейчас требуется, поэтому давайте перейдем к реализации этого примера. Предлагаю не рассматривать по отдельности каждый кусок кода всей программы, а проанализировать весь пример целиком, поле чего остановиться на наиболее непонятных Местах программного кода. В листинге 6.1 показан исходный код рассматриваемого примера.

/**



Текущее время на экране телефона



Рис 6.4. Текущее время на экране телефона



Перейдем к программному коду и рассмотрим пример, реализующий вывод на экран даты и времени одновременно. Все, что сейчас от нас требуется — это написание кода основного класса мидлета, создание пустой формы и встраивание в эту форму класса DateField. Также необходимо проследить наличие команды выхода из приложения. Все остальное за нас сделает Jауа 2 ME, создав кнопки перехода и команду сохранения настроек даты и времени. В листинге 6.2 дается полный код примера к этому разделу.

/**



Пространство созданное классом Spacer



Рис 6.7. Пространство созданное классом Spacer


 



Эмуляторы телефонов показывающие



Рис 6.9. Эмуляторы телефонов, показывающие использование класса Gauge



Параметры конструктора Gauge:

 label - метка или название процесса связанного с объектом Gauge;  interactive - имеются два значения: true для интерактивного режима и false — для не интерактивного режима;  maxValue - максимальное значение, задающее диапазон длительности всего процесса. Может быть установлено при помощи значения INDEFINITE;  static int INDEFINITE - специальное значение, устанавливающее максимальную величину при неизвестном диапазоне течения всего процесса;  initialValue - параметр может быть инициализирован значением от нуля и до значения в параметре maxValue. Этим значением инициализируется начальный отсчет, от которого происходит увеличение визуального представления работы процесса. Кроме числовых значений возможно применение заданных констант:  static int CONTINUOUS_IDLE - задает непрерывное циклическое течение процесса для не интерактивного режима при неопределенном диапазоне;  static int CONTINUOUS_RUNNING -задает непрерывное бегущее течение процесса для не интерактивного режима при неопределенном диапазоне;  static int INCREMENTAL_IDLE- задает пошаговое циклическое течение процесса для не интерактивного режима при неопределенном диапазоне; .  static int INCREMENTAL_UPDATING - задает пошаговое обновление течения процесса для не интерактивного режима при неопределенном диапазоне.


Методы класса Gauge

Методы, имеющиеся в составе класса Gauge, позволяют настраивать графическое отображение течение процесса на экране телефона, рассмотрим некоторые из методов.

 void addCommand (Command cmd) — добавляет команду;  int getMaxValue () — получает значение максимального диапазона работы процесса;  int getValue ()-получает текущее значение в процессе работы;  void setltemCommandListener (ItemCommandListener 1) -устанавливает обработчик событий;  void setLabel (String label) - устанавливает метку для элемента;  void setLayout (int layout) - устанавливает директивы для элемента;  void setMaxValue (int maxValue) - устанавливает максимальное значение течения процесса;  void setPreferredSize(int width, int height) -задает ширину и высоту для графического представления всего течения процесса;  void setValue(int value) - устанавливает текущее значение процесса.


В примере создается простой измеритель течения процесса в виде прямоугольника, максимальный диапазон задан значением десять. В листинге 6.7 показано использование класса Gauge.

/ * *



Информационное уведомление



Рис 6.10. Информационное уведомление, созданное при помощи класса Alert


 



Загрузка изображения классом image



Рис 6.13. Загрузка изображения классом image



Размер шрифта устанавливается при помощи трех констант:

int SIZE_LARGE - большой шрифт;  static int SIZE_MEDIUM - средний шрифт;  static int SIZE_SMALL — маленький шрифт.


Cтиль можно задавать четырьмя константами:

 static int STYLE_BOLD - жирный шрифт;  static int STYLE_ITALIC - курсив;  static int STYLE_PLAIN - обычный шрифт;  static int STYLE_UNDERLINED-подчеркнутый шрифт.


Начертание шрифта определяется тремя константами:

 static int FACE_MONOSPACE - шрифт с небольшим интервалом;  static int FACE_PROPORTIONAL - пропорциональный шрифт;  static int FACE_SYSTEM - системный шрифт.


В профиле MIDP 1.0 возможность установки различных шрифтов в приложении имелась только при использовании класса Graphics и метода setFont (). В профиле MIDP 2.0, уже имеется возможность установки шрифта без использования класса Graphics, только при помощи методов из состава классов пользовательского интерфейса. Процесс назначения шрифта текста в программе происходит следующим образом. Вначале создается переменная, которая будет содержать размер, стиль и начертание шрифта, установленные при помощи метода getFont () класса Font например:

Font myFont = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_BQLD, Font. SI ZE_LARGE) ;

Переменная myFont теперь содержит шрифт, который можно назначит любому тексту в программе. В профиле MIDP 2.0 для этого достаточно вызвать метод setFont () с необходимыми параметрами. В профиле MIDP 1.0 для назначения шрифта тексту, необходимо использовать класс Graphics, в главе 6 рассматривается эта возможность.

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

/**



Эмулятор телефона на



Рис 6.14. Эмулятор телефона, на экране которого представлены разные шрифты



К сожалению, ресурсы мобильных телефонов не позволяют воспользоваться обилием шрифтов компьютерной платформы, но и имеющейся базы вполне достаточно цля создания разнообразных текстовых элементов. Использование шрифтов & программах значительно улучшает пользовательский интерфейс и придает приложению более изящный вид. В следующей главе будет рассматриваться программирование графики в Java 2 ME, с помощью классов низкоуровневого интерфейса.

 


Рисунок" а ImageItem LAYOUT_CENTER



Рисунок",   а, ImageItem.LAYOUT_CENTER,null);

Первым делом создается объект i класса Image, после чего происходит загрузка необходимого изображения посредством вызова метода createlmage () класса Image. Далее создается объект im класса ImageItem, который будет содержать ссылку на объект image.

Изображение, загружаемое в приложение, может находиться в любом месте рабочего каталога. При использовании, например J2ME Wireless Tollkit 2.1, изображение лучше поместить в папку \res. Эта папка по умолчанию для файлов ресурса к разрабатываемому приложению и в этом случае запись /ris.png будет обращаться к папке \res. Если вы хотите использовать другую папку, то необходимо указать весь путь при загрузке изображения, например:

Image  ikon1  = Image.createlmage("/Ikon/Leve12/ikon1.png"};

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

/**

определенный для классов пользовательского интерфейса.



В этой главе...

В Java 2 ME имеется пакет javax.microedition.lcdui, определенный для классов пользовательского интерфейса. Как уже отмечалось в главе 5, классы пользовательского интерфейса разделены на высокоуровневый и низкоуровневый интерфейсы. В этой главе будут последовательно рассмотрены все классы высокоуровневого пользовательского интерфейса. Каждый из разделов содержит информацию об одном конкретном классе, предоставляющем ряд возможностей в оформлении интерфейса пользователя. Используя возможности этих классов, вы сможете создавать в приложении списки, группы элементов, загружать в программу изображения, использовать бегущую строку, назначать шрифт текста и многое другое. В разделах по каждому классу пользовательского интерфейса, анализируются конструкторы, основные методы и константы класса, с помощью которых в конце каждого раздела создается приложение, иллюстрирующее раббту этого класса, и приводится листинг всей программы. При рассмотрении методов и констант классов используется только основные компоненты. Для детального анализа составляющих одного из классов обратитесь к приложению 2, которое выполнено в виде справочника по Java 2 ME.

Единственное, о чем необходимо помнить при проектировании и создании пользовательского интерфейса приложения - это об используемом профиле MIDP. В некоторые классы, имеющиеся в составе профиля MIDP 1.0, были добавлены новые методы, константы и даже классы из профиля MIDP 2.0. Например, в классе ChoiceGroup для профиля MIDP 1.0 доступно тринадцать методов, а уже в профиле MIDP 2.0 их насчитывается семнадцать, то есть, добавлено еще четыре новых. В той же документации по Java 2 ME какой-то четкой грани разделяющей два профиля не существует, но при рассмотрении методов и констант упоминается о принадлежности к одному из профилей. Поэтому при создании приложений, например под профиль, MIDP 1.0, необходимо внимательно планировать разработку программ и не задействовать компоненты профиля MIDP 2-0. Если вы разрабатываете программу для профиля MIDP 2.0, то можете пользоваться всеми имеющимися компонентами вне зависимости от принадлежности к одному из профилей.