SWT предоставляет графический механизм для прорисовки графических объектов и показа изображений в виджетах. Очень многие задачи могут быть выполнены без необходимости программировать графический интерфейс, поскольку виджеты сами управляют прорисовкой значков, текста и других необходимых данных. Но если в вашем приложении отображаются пользовательские графические объекты или вы реализуете свой виджет с графикой, то вам следует изучить некоторые основы рисования объектов в SWT.
Графический контекст, или GC - это центральное звено для поддержки графики в SWT. Его API содержит все функции работы с графикой в SWT.
С помощью GC можно создавать графические изображения в элементах управления (самое распространенное применение), отображать изображения на экране или на принтере. При рисовании управляющего элемента применяется GC, который передается в событии paint управляющего элемента. При рисовании изображения и выводе его на экран или принтер для него следует создать объект GC, а по окончании работы с ним - освободить GC.
Получив GC, можно установить его атрибуты: цвет, толщина линии и шрифт. Эти атрибуты управляют внешним видом рисунка в заданном GC.
Полный набор функций работы с графикой описывается в справочнике по API для GC.
Управление шрифтами в SWT осуществляется с помощью классов Font и FontData.
Класс FontData описывает характеристики шрифта. Класс FontData можно создать путем указания названия, стиля и размера шрифта. В FontData входят API для запроса этих атрибутов. Так как ресурсы ОС для FontData не выделяются, освобождать его не нужно.
Класс Font - это фактически графический объект, представляющий шрифт, используемый в API рисунка. Если необходимо создать Font для Display, то для требуемого шрифта следует указать Display и FontData. Также можно запросить Font для FontData.
По окончании использования выделенный Font следует освободить.
Управление цветом аналогично управлению шрифтами. Если требуется создать Color для Display, то указываются RGB-характеристики желаемого цвета. По окончании работы с выделенным цветом его следует освободить.
Метод getSystemColor(int)
класса Display
позволяет запрашивать предопределенные системные цвета для платформы ОС. Полученные таким образом цвета освобождать не нужно.
Более подробно цветовая модель описывается в статье Цветовая модель SWT.
Для управления изображениями в SWT служат классы Image, ImageData и ImageLoader.
Класс ImageData относится к самим пикселам изображения, описывая используемые цвета с помощью класса PaletteData. Класс ImageData - это машинно- и платформо-независимое описание изображения.
Класс ImageLoader загружает и сохраняет ImageData в различных форматах файлов. На сегодняшний день SWT поддерживает загрузку и сохранение различных форматов, в т.ч.: BMP (растровое изображение Windows), ICO (значок Windows), JPEG, GIF и PNG.
Класс Image - это фактически и есть графический объект, представляющий собой изображение, с которым работает API. Изображение создается для конкретного Display. Изображения можно создавать следующими способами:
Вы должны удалить экземпляр класса Image независимо от того, как он был создан.
Для большинства графических объектов в SWT выделяются ресурсы, поэтому эти ресурсы необходимо явно освобождать. Для этого применяются те же правила, что и описанные выше. Если объект создается с помощью конструктора, то его следует удалить. Если обращение к объекту осуществляется откуда-либо еще, то объект удалять нельзя.
Ресурсы ОС для таких графических объектов, как графические контексты, шрифты, цвета и изображения, выделяются сразу при создании объекта. Определение времени создания объекта зависит от того, как вы планируете его использовать.
Графические объекты, которые планируется интенсивно использовать на протяжении всего приложения, создаются при создании виджетов. Обычно к таким объектам относятся цвета и шрифты. В других случаях графические объекты удобнее создавать "на лету". Например, можно создать графический контекст, выполняющий какие-либо вычисления, в одном из обработчиков события виджета.
Если вы реализуете пользовательский виджет, то ресурсы для "постоянных" графических объектов обычно выделяются в конструкторе. Если объект "временный", или зависит от состояния каких-либо атрибутов, то можно выделять для него ресурсы "на лету".
После создания графического объекта можно начинать его прорисовку. Прорисовку всегда следует делать в получателе запросов paint. Изредка бывает необходимо (особенно при реализации пользовательских виджетов), осуществлять прорисовку при обработке какие-либо других событий. Но вообще-то это не одобряется. Если все же такая необходимость есть, следует сначала попытаться воспользоваться методом redraw(), служащий для генерирования другого события paint. Рисование вне метода paint негативно сказывается на оптимизации платформы и может привести к ошибкам, если в очереди скопится много ожидающих событий paint.
При получении события paint вы получите готовый GC для рисования в виджете. Этот GC освобождать не нужно! Он создан не вами.
Ресурсы для всех остальных графических объектов должны выделяться при обработке события (или до обработки). Ниже приведен фрагмент кода, основанный на примере org.eclipse.swt.examples.HelloWorld5. Красный цвет был создан раньше, при создании виджета, поэтому здесь можно его использовать.
shell.addPaintListener (new PaintListener () { public void paintControl (PaintEvent event) { GC gc = event.gc; gc.setForeground (red); Rectangle rect = event.widget.getClientArea (); gc.drawRectangle (rect.x + 10, rect.y + 10, rect.width - 20, rect.height - 20); gc.drawString (resHello.getString("Hello_world"), rect.x + 20, rect.y + 20); } });
Каждый графический объект, для которого при создании выделены ресурсы, необходимо удалять по окончании работы с ним.
Момент удаления зависит от времени создания объекта. Если при создании виджета создается графический объект, то к виджету как правило, добавляется получатель запросов освобождения, который при удалении виджета освобождает этот объект. Если объект создается "на лету" при обработке paint, то его следует освободить по окончании прорисовки.
В следующем фрагменте показана слегка измененная версия получателя запросов прорисовки. В этом примере во время прорисовки выделяются и освобождаются ресурсы для красного цвета.
shell.addPaintListener (new PaintListener () { public void paintControl (PaintEvent event) { GC gc = event.gc; Color red = new Color (event.widget.getDisplay (), 0xFF, 0, 0); gc.setForeground (red); Rectangle rect = event.widget.getClientArea (); gc.drawRectangle (rect.x + 10, rect.y + 10, rect.width - 20, rect.height - 20); gc.drawString (resHello.getString ("Hello_world"), rect.x + 20, rect.y + 20); red.dispose (); } });