Java. Полное руководство. 8-е издание. С. Н. Тригуб Перевод с английского и редакция
Скачать 25.04 Mb.
|
g .setColor(Color.black); g .drawString("Press mouse button to double buffer", 10, h/2); // g Щелкните для включения двойной буферизации, h/2 ) ; g .setColor(Color.yellow) ; g .fillOval(mx - gap, my - gap, gap*2+l, gap*2+l); if ( !flicker) { screengc.drawlmage(buffer, 0, 0, null); } } public void update(Graphics g) { Этот простой аплет имеет сложный метод paint (). Он окрашивает фон в синий цвета затем рисует поверх него красный муар. Вверху он выводит текст черного цвета и вычерчивает желтую окружность, центр которой определяется по координатам mx, my. Методы mouseMoved () и mouseDragged () заменяются для отслеживания положения курсора мыши. Эти методы идентичны друг другу, за исключением булевой переменной flicker. Метод mouseMoved () присваивает переменной flicker значение true, а метод mouseDragger () — значение false. Это равнозначно эффекту вызова метода repaint (), когда переменная flicker имеет значение true при перемещении курсора мыши (без щелчка ее кнопкой) и значение false — при перемещении курсора мыши с удерживанием кнопки в нажатом состоянии 8 4 4 Часть II. Библиотека Если метод paint () вызывается тогда, когда переменная flicker имеет значение true, мы будем видеть на экране монитора выполнение каждой операции рисования. Если был произведен щелчок кнопкой мыши и метод paint () вызывается, если переменная flicker имеет значение false, будем наблюдать несколько иную картину. Метод paint () заменяет ссылку g на класс Graphics графическим содержимым внеэкранного холста, buffer, который мы создали с помощью метода init () . Затем все операции рисования становятся невидимыми. В завершающей части работы метода paint () мы просто вызываем метод drawlmage () для одновременного отображения результатов всех методов рисования. Обратите внимание на то, что теперь можно передавать методу drawlmage () значение null в четвертом параметре. Этот параметр служит для передачи объекта ImageObserver, который получает извещение о событиях изображения. Поскольку это изображение не формируется из сетевого потока, уведомления ненужны. Левый снимок экрана на рис. 26.2 показывает, как будет выглядеть аплет, если не будет произведен щелчок кнопкой мыши. Как можно заметить, снимок был получен как разв тот момент, когда изображение было наполовину перерисованным. Правый снимок показывает, что при нажатой кнопке мыши изображение оказывается полностью сформированным благодаря использованию двойной буферизации. Рис. 26.2. Результат выполнения аплета DoubleBuffer без использования двойной буферизации (слева) и с использованием двойной буферизации (справа) Класс Объект класса MediaTracker представляет собой объект, который параллельно проверяет состояние произвольного количества изображений. Чтобы использовать класс MediaTracker, нужно создать его новый экземпляр и использовать его метод add Image () для наблюдения за состоянием загрузки изображения. Метод add Image () имеет следующие общие формы addlmage(Image объектИзображения, int идвнтификаторИзображения) void addlmage(Image объектИзображения, int идентификаторИзображения, m t ширина int высота) Здесь параметр объектИзображения представляет отслеживаемое изображение. Его идентификатор передается в параметре идентификаторИзображения. Идентификаторы необязательно должны быть уникальными. Один и тот же идентификатор можно использовать в нескольких изображениях, обозначая их как часть группы. Кроме того, изображения с более низкими идентификаторами при Глава 26. Изображения 8 4 загрузке имеют приоритет перед таковыми с более высокими идентификаторами. Во второй форме параметры ширина ивы сот а определяют размеры объекта при его отображении. После того как изображение будет зарегистрировано, можно проверить, загружено ли оно, или подождать, пока оно полностью не загрузится. Чтобы проверить состояние изображения, вызовите метод checkID () . В этой главе используется следующий вариант этого метода checkID(int идентификаторИзображения) Здесь параметр идентификатор Изображения определяет идентификационный номер изображения, которое вы хотите проверить. Метод возвращает значение true, если были загружены все изображения, имеющие заданный идентификатор (или если процесс загрузки был остановлен вследствие ошибки или прерван пользователем. В противном случае он возвращает значение false. Вы можете использовать метод checkAll () для просмотра, всели наблюдаемые изображения были загружены. Класс MediaTracker следует использовать при загрузке группы изображений. Если все интересующие вас изображения еще не загружены, можете отобразить что-нибудь, чтобы отвлечь пользователя, пока не будут полностью загружены все изображения. Вним ание! Если объект класса MediaTracker использовать после вызова метода ad- dlmage () , то ссылка на класс MediaTracker предотвратит процесс сбора мусора в системе. Если вы хотите, чтобы система могла запускать сборщик мусора относительно отслеживаемых изображений, убедитесь в том, что он будет выполняться ив отношении экземпляра класса Ниже показан пример, в котором загружается семь изображений и отображается привлекательная диаграмма хода выполнения загрузки * * value="vincent+leonardo+matisse+picasso+renoir+seurat+vermeer"> * */ import java.util.*; import java.applet.*; import java.awt.*; public class TrackedlmageLoad extends Applet implements Runnable { MediaTracker tracker; int tracked; int frame_rate = 5; int current_img = 0; Thread motor; static final int MAXIMAGES = 10; Image i m g [] = new Image[MAXIMAGES]; String n a m e [] = new String[MAXIMAGES]; volatile boolean stopFlag; public void ini t () { tracker = new MediaTracker(this); StringTokenizer st = new StringTokenizer(getParameter("img"), " + ") ; w h i l e (st.hasMoreTokens() && tracked <= MAXIMAGES) { name[tracked] = s t .nextToken(); Часть II. Библиотека Java img[tracked] = getlmage(getDocumentBase(), name[tracked] + ".jpg" tracker.addlmage(img[tracked], tracked); tracked++; } public void paint(Graphics g) { String loaded = ""; int donecount = 0; for(int i=0; i if (tracker.checkID(i , true)) { donecount++; loaded += name[i] + " } } Dimension d = getSize(); int w = d.width; int h = d.height; if (donecount == tracked) { frame_rate = 1; Image i = img[current_img++]; int iw = i .getWidth(null); int ih = i .getHeight(null); g .drawlmage(i , (w - iw)/2, (h - ih)/2, null) if (current_img >= tracked) current_img = 0; } else { int x = w * donecount / tracked; g .setColor(Color.black); g .fillRect(0, h/3, x, 16); g .setColor(Color.white); g .fillRect(x, h/3, w-x, 16); g.setColor(Color.black); g .drawString(loaded, 10, h/2); } } public void start() { motor = new Thread(this); stopFlag = false; m o t o r .start(); } public void stop() { stopFlag = true; } public void run() { m o t o r .setPriority(Thread,MIN_PRIORITY); while (true) { repaint(); try { Thread.sleep(1000/frame_rate); } catch (InterruptedException e) { System.out.println("Interrupted"); return; } Глава 26. Изображения 8 4 7 i f (stopFlag) В этом примере создается новый экземпляр класса MediaTracker в методе init ( ) , после чего с помощью метода addlmage () каждое из указанных изображений добавляется как отслеженное. В методе paint () вызывается метод check ID ( ) для каждого изображения, за которым велось наблюдение. После загрузки все изображения будут выведены на экран. В противном случае отображается простая диаграмма, информирующая о количестве загруженных изображений, а под ней выводятся имена полностью загруженных изображений. На рис. 26.3 показаны две сцены из этого выполняющегося аплета. На одной из них видна диаграмма, информирующая о загрузке трех изображений. Другая сцена — это автопортрет Ван Гога вовремя демонстрации слайда leonardo Рис. 26.3. Аплет TrackedlmageLoad вовремя выполнения 8 4 8 Часть II. Библиотека Интерфейс Интерфейс ImageProducer является интерфейсом для объектов, которые должны подготовить данные для изображений. Объект, реализующий интерфейс ImageProducer, задает целочисленный или байтовый массив, представляющий данные изображений, и формирует объекты класса Image. Как вы могли видеть ранее, одна из форм метода createlmage () получает объект интерфейса ImageProducer в качестве своего параметра. Пакет java. awt. im age содержит два производителя изображений — классы MemorylmageSource и FilteredlmageSource. Здесь мы рассмотрим класс MemorylmageSource и создадим новый объект класса Image на основе данных, созданных в аплете. Класс M e m o r y l m a g e S o u r c Этот класс формирует новое изображение класса Image на основе массива данных. Он определяет несколько конструкторов. Ниже показан один из конструкторов, который мы будем использовать ширина int высота int пиксель[], int смещение int ширинаСтрокиРазвертки) Объект класса MemorylmageSource формируется на основе массива целых чисел пиксель в цветовой модели RGB, которая используется по умолчанию для подготовки данных для объекта класса Image. В цветовой модели, используемой по умолчанию, пиксель представляет собой целое число со значениями альфа, красной, зеленой и синей составляющих (OxAARRGGBB). Значение альфа представляет степень прозрачности пикселя. Полностью прозрачному пикселю соответствует нулевое значение, а полностью непрозрачному — значение 255. Значения ширины ивы соты готового изображения передаются в параметрах ширина и высота Начальная точка в массиве пикселей, с которой начнется чтение данных, определяется параметром смещение Ширина строки развертки (которая часто определяет тоже, что и ширина изображения) указывается параметром ширинаСтрокиРаз вертки. В следующем коротком примере создается объект класса MemorylmageSource с помощью разновидности простого алгоритма (побитовое исключающее ИЛИ координат хи у каждого пикселя), взятого из книги Beyond Photography, The Digital Darkroom Джерарда Дж. Хольцманна (Gerard J. Holzmann, Prentice Hall, 1988). /* * * */ import java.applet.*; import j a v a .a w t .*; import j a v a .a w t .image.*; public class MemorylmageGenerator extends Applet { Image img; public void init() { Dimension d = g e t SizeO; int w = d.width; int h = d.height; int p i x e l s [] = new int[w * h ] ; int i = 0; for(int y=0; y |