ImageObserver — это интерфейс, используемый для приема уведомлений о том, как генерируются изображения.
ImageObserver определяет только один метод: ImageUpdate(). Использование наблюдателя изображения позволяет выполнять (параллельно с загрузкой изображения) другие действия, такие как показ индикатора хода работы (progress-индикатора) или дополнительного экрана, которые информируют вас о ходе загрузки. Подобный вид уведомления очень полезен, когда изображение загружается по сети, где проектировщик содержимого редко принимает во внимание, что люди часто пробуют загружать апплеты через медленный модем.
Метод ImageUpdate() имеет следующую общую форму:
boolean imageUpdate(Image imgObj, int flags, int left, int top, int width, int height)
Здесь imgObj — загружаемое изображение, a flags — целое число, которое сообщает состояние отчета обновления. Четыре целых параметра left, top, width и height представляют прямоугольник, который содержит различные значения в зависимости от передаваемых в flags-значений. imageUpdate() должен возвратить false, если он завершил загрузку, и true, если еще имеется остаток изображения для обработки.
Параметр flagsсодержит один или несколько разрядных флажков, определенных как статические переменные внутри интерфейса ImageObserver. Эти флажки и информация, которую они обеспечивают, перечислены в табл. 16.1.
Таблица 16.1. Разрядные флажки параметра flags метода imageUpdate()
Флажок
Значение
WIDTH
Параметр width правилен и содержит ширину изображения
HEIGHT
Параметр height правилен и содержит высоту изображения
PROPERTIES
Свойства, связанные с изображением могут теперь быть получены через imgObj.getProperty()
SOMEBITS
Получена следующая порция пикселов, необходимых для вывода изображения. Параметры left, top, width, и height определяют прямоугольник, содержащий новые пикселы
FRAMEBITS
Получен полный фрейм, являющийся частью многофреймового изображения, которое было предварительно нарисовано. Данный фрейм может быть отображен. Параметры left, top, width и height не используются
ALLBITS
Изображение выведено целиком. Параметры left, top, width
и height не используются
ERROR
Произошла ошибка с изображением, которое прослеживалось асинхронно. Изображение неполно и не может быть отображено. Никакая дальнейшая видеоинформация не будет получена. Для удобства будет также установлен флажок ABORT, чтобы указать, что производство изображения было прервано
ABORT
Изображение, которое прослеживалось асинхронно, было прервано прежде, чем оно было закончено. Однако, если ошибка не произошла, доступ к любой части данных изображения перезапустит
Класс Applet имеет реализацию метода imageUpdate() интерфейса ImageObserver, который используется для перерисовки изображений во время их загрузки. Его можно переопределить в вашем классе, чтобы изменить поведение метода.
Простой пример метода imageUpdate():
public boolean imageUpdate (Image img, int flags,
int x, int y, int w, int h) {
if ((flags & ALLBITS) == 0) {
System.out.println("Загрузка изображения...");
return true;
}
else {
Applet imageupdate ImageObserver, imageupdate ():
System.out.println("Загрузка изображения завершена.");
return false;
}
}
На рис. 1 показана работа апплета с отображенной картинкой.
Рис. 1. Отображение рисунка в окне апплета
Пример с ImageObserver
Теперь рассмотрим пример, который переопределяет imageUpdate() так, чтобы избавить версию апплета SimpleImageLoad от частого мерцания изображения. Умалчиваемая реализация imageUpdate() в классе Applet имеет несколько проблем. Во-первых, она перерисовывает полное изображение каждый раз, когда прибывают какие-нибудь новые данные. Это вызывает вспышки между цветом фона и изображением. Во-вторых, он использует свойство Applet.repaint(), заставляющее систему перерисовывать изображение только каждую десятую долю секунды или около этого. Это вызывает чувство толчкообразного, негладкого движения изображения при его рисовании. Наконец, заданная по умолчанию реализация не знает ничего относительно изображений, которые могут быть не в состоянии загружаться должным образом. Многие начинающие программисты Java недовольны тем, что метод getlmage() преуспевает даже тогда, когда указанное изображение не существует. Вы не узнаете об отсутствии изображения, пока не начнет работу imageUpdate(). Если вы используете умалчиваемую реализацию imageUpdate(), то никогда и не узнаете, что случилось. Ваш метод paint() просто не будет ничего делать, когда вы вызываете g.drawImage().
Следующий ниже пример фиксирует все три этих проблемы в десяти строках кода. Во-первых, он устраняет мерцание с помощью двух небольших изменений. Он переопределяет метод update() так, чтобы тот вызвал paint() без первоначальной прорисовки цвета фона. Фон устанавливается через метод setBackground() в init(), так что начальный фон рисуется только однажды. Он также использует версию метода repaint(), которая указывает прямоугольник для рисования. Система установит область отсечения такой, чтобы ничего вне данного прямоугольника не рисовалось. Это устраняет мерцание перерисовки и улучшает исполнение.
Во-вторых, это избавит от толчкообразного, негладкого показа входящего изображения путем перерисовки каждый раз, когда repaint() принимает обновление. Эти обновления происходят на базе построчного сканирования, так что изображение, которое имеет 100 пикселов в высоту, будет "перерисовываться" 100 раз за время загрузки. Обратите внимание, что это не самый быстрый способ отображать изображение, а лишь самый сглаженный.
Наконец, он обрабатывает ошибку, вызванную тем, что нужный файл не найден, исследуя ABORT-разряд параметра flags. Если он установлен, переменная экземпляра error принимает значение true, и затем вызывается repaint (). Метод paint() модифицируется так, что, если переменная error равна true, то сообщение об ошибках печатается на ярко-красном фоне.