Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
2013_1 / ООП / Введение_SWG.pdf
Скачиваний:
82
Добавлен:
23.02.2015
Размер:
3.32 Mб
Скачать

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

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

Shell shell = new Shell ();

Listener listener = new Listener () { public void handleEvent (Event e) {

switch (e.type) { case SWT.Resize:

System.out.println ("Resize received"); break;

case SWT.Paint:

System.out.println ("Paint received"); break;

default:

System.out.println ("Unknown event received");

}

}

};

shell.addListener (SWT.Resize, listener); shell.addListener (SWT.Paint, listener);

1.5 Работа с подпроцессами

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

23

1.5.1 Диспетчеризация внутренних событий

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

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

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

1.5.2 Нить пользовательского интерфейса SWT

Модель управления нитями в SWT строится на принципе поддержки непосредственно платформой. Прикладная программа запускает в своей главной нити цикл событий и извлекает события прямо из нее. Нить пользовательского интерфейса — это нить, в которой был создан виджет класса Display. Все остальные виджеты должны создаваться в этой же нити.

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

24

Примечание: Для любого вызова, который должен был быть сделан из нити UI, а выполняется из другой нити, SWT генерирует исключительную ситуацию SWTException.

Главная нить, включающая цикл событий, для приложения SWT имеет следующую структуру:

public static void main (String [ ] args) { Display display = new Display ();

Shell shell = new Shell (display); shell.open ();

//start the event loop. We stop when the user has done

//something to dispose our window.

while (!shell.isDisposed ()) {

if (!display.readAndDispatch ()) display.sleep ();

}

display.dispose ();

}

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

1.5.3 Выполнение кода за пределами нити UI

Приложения, требующие вызова кода UI не из нити UI, должны поддерживать метод Runnable, вызывающий код UI. Для выполнения этого кода в нити UI во время цикла событий служат методы syncExec(Runnable) и asyncExec(Runnable) класса Display.

syncExec(Runnable) используется, если код приложения в не-UI нити зависит от значения, возвращенного из кода UI, или когда требуется убедиться, что выполняемый код завершается перед возвращением в нить. SWT будет блокировать вызывающую нить до тех пор, пока выполняется код, запущенный из нити UI. Например, фоновая нить, которая что-либо вычисляет на основе текущих размеров окна, должна синхронно запустить код для получения размера окна и потом продолжить вычисления.

Метод asyncExec(Runnable) используется, если приложению требуется выполнить какие-либо операции UI, завершение которых перед возвращением в нить не важно. Например, фоновая нить, обновляющая индикатор выполнения или перерисовывающая окно, может асинхронно запрашивать обновление и

25

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

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

//долгие вычисления

...

//теперь обновляется UI. Нам не важен результат,

//поэтому используем async.

display.asyncExec (new Runnable () { public void run () {

if (!myWindow.isDisposed()) myWindow.redraw ();

}

}); // продолжаем вычисления

...

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

1.5.4 Рабочая среда и нити

Правила управления нитями достаточно просты при реализации приложения SWT с нуля, так как вы управляете созданием цикла событий и принимаете решение о порождении вычислительных нитей в приложении.

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

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

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

Аналогично, библиотека пользовательского интерфейса платформы также не учитывает нити, если явно не указано обратное. Большинство классов

26

пользовательского интерфейса отделяет обработчики событий из вызывающей нити. Вызовы API рабочей среды и JFace не проверяют, выполняется ли вызывающая программа в нити UI. Это означает, что вызов из вашего модуля метода, порождающего событие, из не-UI нити может привести к неполадкам. Если вызов API осуществлен из не-UI нити, SWT генерирует исключительную ситуацию класса SWTException. Поэтому желательно избегать вызовов методов UI из не-UI нитей, кроме случаев, когда в javadoc это разрешено явно.

Если ваш модуль порождает вычислительную нить или использует задание рабочей среды, в нем следует использовать либо метод asyncExec(Runnable), либо syncExec(Runnable) класса Display, вызывающие API для рабочей среды, JFace или SWT.

Если вызов монитора выполнения и запуск операции в модуле осуществляются с помощью интерфейса IRunnableContext JFace, то он предоставляет аргумент, указывающий, порождена ли для выполнения операции вычислительная нить.

27

Соседние файлы в папке ООП