p align="left">height += currentStyle.getMargin (Component.TOP) + d.getHeight() + currentStyle.getMargin (Component.BOTTOM); } Dimension size = new Dimension (width, height); return size; } } В следующем листинге 3.3 содержится программный код экранной формы-заставки с применением разработанного класса-менеджера размещения элементов CenterLayout. Листинг 3.3 - Экранная форма заставки public class SplashScreen extends Form { public SplashScreen() { setLayout (new CenterLayout()); setTitle ("Welcome"); addComponent (new Label(("Video observer"))); addComponent (new Label(("by M. Luskanova"))); } } 62 Рисунок 3.2 - Главное меню Для создания главного меню (рисунок 3.2) был реализован специальный класс, который представляет собой один пункт меню. Каждый элемент такого меню является контейнером с несколькими строчками и представляет их как единое целое. Такая функциональность достигается за счет наследования от класса Container и переопределения методов getComponentAt() и pointerPressed() (листинг 3.4). Метод getComponentAt (int x, int y) вызывается, когда необходимо вернуть компонент, находящийся в заданной точке экрана. Если этот метод не переопределить, то будет возвращен элемент, входящий в данный контейнер. Переопределение второго метода гарантирует, что не произойдет никакой обработки (например, выделения) в случае, если пользователь выберет какой-либо элемент данного пункта. Метод pointerPressed (int x, int y) выполняется в случае нажатия сенсорного указателя. Если этот метод не переопределить, то будет выделен компонент внутри данного контейнера. Листинг 3.4 - Пункт главного меню public class MylistItem extends Container implements FocusListener { private Style selectedStyle = UIManager.getInstance().getComponentStyle ("_selected"); private Style unselectedStyle = UIManager.getInstance().getComponentStyle ("_unselected"); /** * This method provides performance of * included components as one */ public Component getComponentAt (int x, int y) { return this; } /** * Do nothing when user clicks on any element */ public void pointerPressed (int x, int y) { } /** * Returns "_unselected" style by default */ protected String getUIID() { return "_unselected"; } /** * Change style for selected menu item */ public void focusGained (Component cmp) { cmp.setStyle(selectedStyle); } /** * Change style for unselected menu item */ public void focusLost (Component cmp) { cmp.setStyle(unselectedStyle); } } Метод getUIID() переопределен для того, чтобы возвращать стиль невыделенного элемента. Метод focusGained() вызывается при получении данным пунктом меню фокуса, и поэтому требуется этот пункт отрисовать другим стилем. При перемещении фокуса на следующий пункт меню нужно поменять стиль этого пункта на обычный, что и выполняется в переопределенном методе focusLost(). Само меню создается следующим образом с использованием вышеуказанного класса (листинг 3.5). Preferences.getInstanse() - это объект, который хранит все сделанные пользователем настройки. Листинг 3.5 - Создание главного меню Preferences pr = Preferences.getInstanse(); setLayout (new BoxLayout (BoxLayout.Y_AXIS)); getContentPane().setIsScrollVisible(false); MylistItem mli = new MylistItem (MainMenuConstatns.SCHEDULE, "Schedule"); if (! pr.isStartRecordFromUnbounded()) { mli.addString ("from" + pr.getStartRecordFromCalendar().get (java.util. Calendar.YEAR) +"." + pr.getStartRecordFromCalendar().get (java.util. Calendar.MONTH) +"." + pr.getStartRecordFromCalendar().get (java.util. Calendar.DAY_OF_MONTH) +" "+pr.getStartRecordFromCalendar().get (java.util. Calendar.HOUR_OF_DAY) +":"+pr.getStartRecordFromCalendar().get (java.util. Calendar.MINUTE)); } if (! pr.isEndRecordAtUnbounded()) { mli.addString ("till" + pr.getEndsRecordAtCalendar().get (java.util. Calendar.YEAR) +"." + pr.getEndsRecordAtCalendar().get (java.util. Calendar.MONTH) +"." + pr.getEndsRecordAtCalendar().get (java.util. Calendar.DAY_OF_MONTH) + " " + pr.getEndsRecordAtCalendar().get (java.util. Calendar.HOUR_OF_DAY) +":" + pr.getEndsRecordAtCalendar().get (java.util. Calendar.MINUTE)); } if (! pr.isStartRecordFromUnbounded() ||! pr.isEndRecordAtUnbounded()) { if (pr.isScheduleIsActive()) { mli.addString ("Active"); } else { mli.addString ("Disabled"); } } addComponent(mli); mli = new MylistItem (MainMenuConstatns.TRANSLATE_VIDEO, "Translate video"); addComponent(mli); if (pr.getBTConnectionURL()!= "") { mli.addString ("via bluetooth to "+pr.getBTFriendlyName()); } if (pr.getSaveVideoToFile()!= "") { mli.addString (pr.getSaveVideoToFile()); } if (pr.getMovNotification()!= "") { String msgType = (pr.isSendSMS()? "sms": "mms") +" to"; addComponent (new MylistItem (MainMenuConstatns.MOVEMENT_NOTIFICATION, new String[] {"Movement notification", msgType + pr.getMovNotification()})); } else { addComponent (new MylistItem (MainMenuConstatns.MOVEMENT_NOTIFICATION, "Movement notification")); } if (pr.getErrNotificationNumber()!= "") { addComponent (new MylistItem (MainMenuConstatns.ERROR_NOTIFICATION, new String[] {"Error Notification", pr.getErrNotificationNumber()})); } else { addComponent (new MylistItem (MainMenuConstatns.ERROR_NOTIFICATION, "Error Notification")); } addComponent (new MylistItem (MainMenuConstatns.CAMERA, "Camera")); addComponent (new MylistItem (MainMenuConstatns.EXIT, "Exit")); addComponent (new MylistItem (MainMenuConstatns.HELP, "Help")); Обработка нажатия пользователем кнопок и определение, какая экранная форма должна быть показана далее, выполняется так, как показано в следующем листинге 3.6. Листинг 3.6 - Обработка нажатий кнопок для главного меню class MainMenuActionListener implements ActionListener { public void actionPerformed (ActionEvent act) { Component cmp = getFocused(); if (cmp instanceof MylistItem) { int id = ((MylistItem) cmp).getId(); switch (id) { case MainMenuConstatns.SCHEDULE: midlet.getScheduleDisplay().show(); break; case MainMenuConstatns.TRANSLATE_VIDEO: midlet.getVideoTransmitionDisplay().show(); break; case MainMenuConstatns.MOVEMENT_NOTIFICATION: midlet.getMovementNotificationDisplay().show(); break; case MainMenuConstatns.CAMERA: midlet.getCamera().show(); midlet.getCamera().startCamera(); midlet.getCamera().revalidate(); break; case MainMenuConstatns.EXIT: midlet.exitMIDlet(); break; case MainMenuConstatns.HELP: midlet.getHelpScreen().show(); break; case MainMenuConstatns.ERROR_NOTIFICATION: midlet.getErrorNotification().show(); break; } } } На форме настройки расписания (рисунок 3.3) необходимо было реализовать динамическое скрытие / отображение некоторых элементов, а именно: когда выбирается радиокнопка enter time, то должны сразу под ней отобразиться поля для ввода часов, минут, дня, месяца, года. А при выборе радиокнопки unbounded эти поля должны быть скрыты. 62 Рисунок 3.3 - Заполнение расписания работы камеры Такая функциональность реализуется путем указания у каждой радиокнопки ActionListener, который отслеживает выбор радиокнопок (листинг 3.7). dateFrom и dateTo являются контейнерами типа Container и содержат все необходимые поля для указания точной даты и времени. Листинг 3.7 - Обработка выбора радиокнопок public void actionPerformed (ActionEvent evt) { Component cmp = (Component) evt.getSource(); if (cmp == rb1DateFromEnter) { if (rb1DateFromEnter.isSelected()) { if (! getContentPane().contains(dateFrom)) { addComponent (3, dateFrom); revalidate(); return; } } } if (cmp == rbDateFromUnbounded) { if (getContentPane().contains(dateFrom)) { removeComponent(dateFrom); revalidate(); return; } } if (cmp == rbDateToEnter) { if (rbDateToEnter.isSelected()) { if (! getContentPane().contains(dateTo)) { addComponent (getContentPane().getComponentCount() - 2, dateTo); dateTo.setFocus(true); revalidate(); return; } } } if (cmp == rbDateToUnbounded) { if (getContentPane().contains(dateTo)) { removeComponent(dateTo); revalidate(); return; } } } Рисунок 3.4 - Экранная форма со списком Для всех списков в данном приложении разработан специальный способ их отображения - класс MyListCellRenderer. По умолчанию для отображения списков применяется DefaultListCellRenderer, который просто преобразовывает все элементы к объектам класса Label. Для создания своего способа отображения элементов списка необходимо реализовать интерфейс ListCellRenderer. Метод getListCellRendererComponent этого интерфейса должен возвращать отображаемый элемент списка из объекта, передаваемого ему в качестве параметра. Переопределение методов getListFocusComponent обеспечивает возможность настройки стилей отображения выделенного и невыделенного элемента списка. Пример списка, реализованного с помощью MyListCellRenderer, приведен на рисунке 3.4. В листинге 3.8 приведен программный код класса, который прорисовывает список. Листинг 3.8 - Прорисовка списка public class MyListCellRenderer extends Container implements ListCellRenderer { public MyListCellRenderer() { setLayout (new BoxLayout (BoxLayout.Y_AXIS)); } /** * Returns displayable list element from received object */ public Component getListCellRendererComponent (List list, Object value, int index, boolean isSelected) { if (value instanceof String) { setText((String) value); } else { setText (value.toString()); } setFocus(isSelected); applyStyle (this, isSelected); return this; } /** * Applies style for selected and unselected element */ private void applyStyle (Component component, boolean isSelected) { Style style = null; if (isSelected) { style = UIManager.getInstance().getComponentStyle ("_selected"); } else { style = UIManager.getInstance().getComponentStyle ("_unselected"); } component.setStyle(style); } public Component getListFocusComponent (List list) { return null; }
Страницы: 1, 2, 3, 4, 5, 6
|