Часть 1 про flash9 и aswing
Материал из Dom.
[править] Дорога из желтого кирпича: строим пользовательские интерфейсы вместе с Flash 9 & ASWing. Часть 1
Вот и вышел новый flash cs3. Почти два года разработки, покупка macromedia компанией adobe, множество обещаний при разработке следующей версии учесть пожелания, как программистов, так и дизайнеров, и все это закончилось грандиозным ничем. Эта статья начнет серию материалов, в которых я буду рассказывать про хорошие идеи хороших людей, которые не ждут манны небесной от adobe, а создают библиотеки, языки и методики программирования на flash-платформе пытаясь придать ей более профессиональный вид. Сразу предупреждаю, все, о чем я пишу и рассуждаю далее, я рассматриваю с точки зрения только программирования, но не дизайна во flash. Когда adobe купила macromedia, было множество заявлений об грядущих перспективах широкого внедрения flash, но не как программы для создания роликов на веб-сайтах или мультиков с масяней. А именно как платформы работающей и в среде браузера и в мобильных устройствах и, более того, даже проникновение на рынок desktop приложений. Flash - как среда тесно проинтегрированная с html/css/pdf для построения и настройки внешнего вида. Среда, обладающая развитыми методиками взаимодействия с веб-сайтами и веб-службами, социальными сетями. Среда, которая могла бы реально сгладить различия между веб-приложениями и настольными (desktop) программами. Ладно, ладно, я слышал эти обещания еще в далеком 98-ом, но сейчас мир, похоже, действительно меняется. Подтверждали эти намерения и выход alpha версии apollo и быстрый выход серии средств разработки flex. Почувствовав запах денег, зашевелились microsoft и sun. Microsoft предлагает среду разработки silverlight, основанную на интеграции .net|xaml и возможностей браузера. Sun уже имея неудачный опыт выхода на этот рынок с технологией jnlp, пытается сделать вторую попытку и представляет javaFX. Было бы неплохо, если бы у нас была возможность удобно устроиться в кресле и понаблюдать чем закончится битва титанов, но вся проблема в том, что нам нужно писать код и разрабатывать веб-приложения сейчас. А чем сложнее задача, тем больше для нас важны не рекламные проспекты пиар-отделов и пространные статьи евангелистов каждого из подходов. Достаточно опытному программисту не интересны статьи с примерами из пяти строк показывающие как легко он будет решать свои задачи. Ему более важны примеры того, как он будет избегать тех ошибок и проблем, с которыми он уже столкнулся раньше. Значит, нам нужны отлаженные, удобные и простые средства, для того чтобы быстро и удобно писать код, быстро компилировать, быстро отлаживать, быстро развертывать и оптимизировать код. Так о чем я буду писать? О среде разработке FlashDevelop, которая в десяток раз удобнее, чем встроенный редактор flash cs3. О языке haxe. О компиляторе MTASC, который работает в разы быстрее, чем стандартный компилятор flash. О библиотеке ASWing для построения пользовательских интерфейсах. О внедрении SVN и ant для организации коллективной работы и автоматизации сценариев. О методах тестирования кода. Обо всем том, что позволяет оставить от всего flash только один flashplayer и наслаждаться этим.
Тема сегодняшней статьи - библиотека создания пользовательских интерфейсов ASWing.
Существуют две основные версии этой библиотеки: ASWing2 и ASwing3. Первая из них ориентируется на actionscript2, и вы можете ее использовать для написания кода в macromedia flash 8. Вторая же версия ориентирована на actionscript3 и, следовательно, в список инструментов, где можно применять aswing входит не только недавно вышедшая версия adobe flash cs3, но и adobe flex 2, и готовящийся к выходу flex 3 (пока он доступен в виде ранних бетаверсий). Также aswing3 можно использовать совместно с adobe AIR (в девичестве apollo). Хотя я практически не попробовал ASWing2, но с первого взгляда кардинальных отличий между ASwing2 и ASwing3 я не нашел. Проще говоря, ASwing3 это эволюционный шаг вперед от ASwing2, а вовсе не революционная перестройка.
Мне как хорошо знакомому с библиотекой Swing (стандартная java библиотека служит для построения GUI) сразу показались знакомыми иерархии классов и подход с четким отделением данных от их визуализации. Чем больше я рассматривал примеры и читал документацию, тем больше удостоверялся в том, что идеи swing оставили неизгладимый след на разработчиков ASWing. Я попробовал библиотеку ASwing в паре своих проектов и остался доволен, надеюсь, что и вам она понравится. Домашняя страница библиотеки http://www.aswing.org.
Весь дальнейший код пишется в Flash cs3, хотя с равным успехом мог быть написан в Flex Builder, FlashDevelop или в любом другом редакторе. Итак, вы скачали и распаковали архив библиотеки. Отличия только в способе подключения библиотеки, так для Flash cs3 вам необходимо зайти в меню “Edit -> Preferences -> закладка ActionScript -> кнопка ActionScript 3 Settings”. В появившемся диалоговом окне выберите путь к каталогу, где находятся исходники ASwing (это подкаталог исходного архива с названием src). Если вы используете flex builder то на стадии создания нового проекта вам необходимо указать путь к файлу библиотеки (она называются AsWingA3.swc и находится в подкаталоге bin).
После чего вы создаете новый проект с типом ActionScript3 и импортируете несколько основные пакеты библиотеки и выполняете первичную настройку Aswing. В частности надо запретить масштабирование графического содержимого приложения (за это отвечает свойство stage.scaleMode), а также неплохо отключить выделение текущего элемента с помощью специальной рамки (поведение flash по-умолчанию). Затем мы должны начать конструировать собственно интерфейс. Все компоненты ASWing делятся на две категории собственно компоненты и их контейнеры. Все контейнеры наследуются от класса org.aswing.Container часть их: JList, JMenuBar, JPanel, JPopupMenu, JRootPane, JScrollPane, JSplitPane, JTable, JTableHeader, JToolBar, JToolTip, JTree, JViewport. Сходность названий с названиями аналогичных по функциональности классов в мире java swing не единственное общее между этими двумя библиотеками. В aswing реализована концепция менеджеров раскладок. Каждый контейнер имеет некоторый привязанный к нему менеджер раскладки, в некоторых ситуациях эти менеджеры можно менять друг на друга, иногда это не допустимо. Идея менеджера раскладки в том, что мы не задаем положение элементов графического интерфейса жестко, мол, эта кнопка будет находиться в таких то координатах и иметь такой то размер с точностью до пикселя. Первоначально, когда java ориентировался на выполнение кода на различных платформах с различными реализациями графических элементов, точное позиционирование было, скорее зло, чем благо. Согласитесь сами, что внешний вид кнопок, меню и других компонентов отличен для windows, mac или motif. С широким распространением концепции skin-ов для программ или для всей операционной системы в целом, идея абсолютного позиционирования элементов GUI не приобрела дополнительных плюсов. Если задуматься еще о задаче создания локализованных версий вашего программного продукта, то становится очевидно что подход когда на кнопку “Выход” отводилось по ширине ровно 50px уже не пройдет. Потому что на каком-нибудь языке тумба-юмба слово “Выход” состоит из доброй сотни символов и элементарно не влезает в отведенное ему место. Так что концепция менеджеров раскладок, когда элементы выстраиваются основываясь на их реальных или предпочитаемых размерах, являются наилучшей. Традиционно каждый элемент GUI сообщает менеджеру раскладки, какие размеры являются для него минимально допустимыми, какие максимально предельные и какие размеры идеальны или предпочитаемые. Менеджер раскладки отводит место для элемента так, чтобы попасть в отрезок между минимальными и максимальными размерами. Но вовсе не факт, то, что размер будет совпадать с предпочитаемым, ведь надо еще учитывать интересы и соседних элементов, у которых тоже есть свои минимальные, максимальные и предпочитаемые размеры.
Итак, у каждого контейнера есть метод setLayout(layout:LayoutManager). В качестве единственного параметра, которому можно передать менеджера раскладки. Вот полный список этих менеджеров: BorderLayout, BoxLayout, CenterLayout, EmptyLayoutUIResourse, FlowLayout, GridLayout, ScrollPaneLayout, SoftBoxLayout, VerticalLayout, ViewportLayout, WindowLayout. Снова дежа-вю, эти классы я уже многократно видел в java swing. Для тех, кто со swing не работал, мы попробуем сейчас сделать простой пример и показать пару раскладок в действии. Пусть, это будет программа калькулятор. Условно она будет состоять из двух текстовых полей для ввода чисел операндов, четырех кнопок для вызова соответствующих математических операций и текстового поля в котором будет отображаться результат.
Выглядеть конечный результат будет как на рис. 1.
Обратите внимание на то, что у меня есть четыре “полосы” расположенных друг на друге, в каждой из “полос” располагается либо пара элементов текстовая надпись и поле для ввода текста, либо набор из четырех кнопок. Прежде всего, я создаю панель, на которой будет расположено абсолютно все. Но как теперь сказать, что это абсолютно все должно располагаться по вертикали? Нам нужно назначить панели раскладку BoxLayout. В качестве параметров конструктору передается способ раскладки (по вертикали или по горизонтали), а также расстояние между компонентами. Следующий шаг - это добавить на панель еще четыре панели, каждая из которых будет иметь туже раскладку BoxLayout, но уже горизонтальную. Последний шаг это размещение собственно текстовых полей, надписей и кнопок внутрь этих четырех панелей. Последним шагом будет вызов метода validate для панели верхнего уровня. Этот вызов служит для того, чтобы все контейнеры попросили свои менеджеры раскладки пересчитать расположение всех дочерних элементов. Всякий раз, когда вы программно изменяете внешний вид приложения, добавляя или удаляя компоненты GUI желательно вызывать этот перерасчет.
Для создания надписи мы используем класс JLabel. “Надпись” умеет отображать не только текст, но и маленькую картинку “иконку”. Эти параметры и следует передать конструктору класса. Для создания иконки я использовал класс класс LoadIcon, для которого необходимо указать параметр конструктора с именем файла картинки, загрузка файла с картинкой в память будет выполнена автоматически. Как вариант можно использовать класс AttachIcon, в качестве параметра конструктора которому следует передать имя внедренного в библиотеку изображения. После импорта изображения в библиотеку незабудьте разрешить для этой картинки доступ из actionscript и дать ей некоторое имя, которое и будет передано в качестве параметра конструктору AttachIcon. Интересный прием заключается в использовании специального объекта Loader-а, позволяющего указать, откуда именно будет выполнена загрузка изображения. Так я пробовал создавать специальный файл swf с набором картинок выступающий в роли репозитария ресурсов для основного приложения, хотя подход с LoadIcon мне показался все же удобнее. Единственный неприятный момент при работе с иконками – это то, что нельзя один и тот же объект иконки привязять сразу к нескольким JLabel. В этом случае только одна надпись (та к которой иконка была присоединена последней) будет с иконкой.
Для создания текстового поля мы применяем класс JTextField. Кнопка – это класс JButton. Для его создания достаточно указать название кнопки, и необязательный параметр – иконку. Теперь нам следует указать обработчик событий нажатия на каждую из кнопок. Для этого вы должны вызвать метод addActionListener от имени кнопки и передать в качестве параметра этого метода ссылку на функцию, которая и будет вызвана при активации кнопки. В примере ниже установил как обработчик события для всех четырех кнопок одну единственную функцию. Дело в том, что код вычисления будет, по сути, идентичен за исключением, собственно, операции. Следовательно, внутри функции достаточно определить какая именно из четырех кнопок была активирована и выполнить для нее небольшое специфическое действие (собственно вычисление). Обратите внимание, что в качестве параметра функции передается специальный объект AWEvent, содержащий сведения о событии и в частности, об элементе интерфейса, который это событие инициировал. Ссылка на этот элемент хранится в поле “target”. Так как мы делаем хороший калькулятор, то необходимо выполнить проверку введенных значений операндов на корректность, и если какое либо из чисел не указано, то необходимо вывести сообщение об ошибке. Забудьте об trace! В составе ASwing есть поддержка всплывающих диалоговых окон. Для этого используется класс JOptionPane. В нем есть два статических метода showMessageDialog и showInputDialog. Которые служат соответственно для вывода окна сообщения, и для создания диалогового окна для ввода некоторой текстовой величины.
На рисунке 2 показаны примеры различных диалоговых окон. Также не забывайте, что из-за особенностей flash даже если вы укажите для некоторого диалогового окна признак модальности, то все равно вычисление будет продолжаться далее.
// подключаем нужные для работы ASWing библиотеки import flash.display.*; import org.aswing.*; import org.aswing.event.AWEvent; import flash.text.*; // отключаем масштабирование рабочей области экрана stage.scaleMode = StageScaleMode.NO_SCALE; // запрещаем подсветку текущего элемента stage.stageFocusRect = false; // указываем корень дерева всех элементов ASwing AsWingManager.setRoot(this); var ico : LoadIcon = new LoadIcon ("ico_fla9_1.PNG"); JOptionPane.showMessageDialog("Сообщение", "Нажмите одну из этих кнопок", onMessageFoo ,null, true, ico, JOptionPane.YES|JOptionPane.NO); trace("bar"); JOptionPane.showInputDialog("Сообщение", "Введите ваше имя", onInputFoo, "George" ,null, true, ico); function onMessageFoo(r : int):void { trace("got"); } function onInputFoo(r : String):void { trace("enter"); } А вот полный пример кода для приложения калькулятора. // подключаем нужные для работы ASWing библиотеки как и в предыдущем примере var panel_top:JPanel = new JPanel(); panel_top.setLayout(new BoxLayout (BoxLayout.Y_AXIS, 10) ); var panel_1:JPanel = new JPanel(); panel_1.setLayout(new BoxLayout (BoxLayout.X_AXIS, 10) ); var panel_2:JPanel = new JPanel(); panel_2.setLayout(new BoxLayout (BoxLayout.X_AXIS, 10) ); var panel_3:JPanel = new JPanel(); panel_3.setLayout(new BoxLayout (BoxLayout.X_AXIS, 10) ); var panel_4:JPanel = new JPanel(); panel_4.setLayout(new BoxLayout (BoxLayout.X_AXIS, 10) ); var ico_1 : LoadIcon = new LoadIcon ("ico_fla9_1.PNG"); var ico_2 : LoadIcon = new LoadIcon ("ico_fla9_2.PNG"); // создаем надписи panel_1.append(new JLabel ("Первое число: ")); panel_2.append(new JLabel ("Второе число: ")); // создаем текстовые поля var txt_a: JTextField = new JTextField (); panel_1.append(txt_a); var txt_b: JTextField = new JTextField (); panel_2.append(txt_b); // создаем набор из четырех кнопок var btnPlus : JButton = new JButton ("+", ico_2); var btnSubtract : JButton = new JButton ("-"); var btnMultiply : JButton = new JButton ("*"); var btnDivide : JButton = new JButton ("/"); // указываем обработчики событий для этих кнопок btnPlus.addActionListener(__buttonActionAnyOperation); btnSubtract.addActionListener(__buttonActionAnyOperation); btnMultiply.addActionListener(__buttonActionAnyOperation); btnDivide.addActionListener(__buttonActionAnyOperation); panel_3.append(btnPlus); panel_3.append(btnSubtract); panel_3.append(btnMultiply); panel_3.append(btnDivide); panel_4.append(new JLabel ("Результат вычислений: ", ico_1)); var txt_c: JTextField = new JTextField (); panel_4.append(txt_c); //добавляем созданные панели-полосы на родительскую панель panel_top.append(panel_1); panel_top.append(panel_2); panel_top.append(panel_3); panel_top.append(panel_4); panel_top.setSizeWH(400, 140); // добавляем на stage корневой элемент панели addChild(panel_top); panel_top.validate(); // здесь мы определяем обработчики событий function __buttonActionAnyOperation(e:AWEvent):void { var btn:JButton = e.target as JButton; // тест на проверку того что оба числа были введены if (txt_a.getText () == "" || txt_b.getText () == "") { JOptionPane.showMessageDialog("Ошибка", "Обязательно следует ввести оба значения"); return; } // преобразуем содержимое текстовых полей в число var a : Number = parseFloat (txt_a.getText ()); var b : Number = parseFloat (txt_b.getText ()); // выполняем проверку введенных строк текста if (isNaN(a)) { JOptionPane.showMessageDialog("Ошибка", "Введеное в первое поле значение не является числом"); return; } if (isNaN(b)) { JOptionPane.showMessageDialog("Ошибка", "Введенное во второе поле значение не является числом"); return; } var c : Number; if (btn == btnPlus) {c = a + b;} if (btn == btnSubtract) {c = a - b; } if (btn == btnMultiply) {c = a * b;} if (btn == btnDivide) {c = a / b;} txt_c.setText(c.toString()); }
Полагаю, что первое знакомство с ASWing состоялось. В следующий раз я рассмотрю более сложные и интересные возможности ASWing. Мы попробуем работать с наборами закладок, таблицами, списками, получим представление о модели данных для компонентов ASWing.
|
|
Subscribe Now! |
|


