Java. Полное руководство. 8-е издание. С. Н. Тригуб Перевод с английского и редакция
Скачать 25.04 Mb.
|
8 3 1 ACTION_EVENT_MASK KEY_EVENT_MASK ADJU S TMENT_EVENT_MAS К S E_MO К S E_MOTION_EVENT_MASK FOCUS_EVENT_MASK TEXT_EVENT_MASK INPUT_METHOD_EVENT_MASK WINDOW_ E V E N T _ M A S К ITEM_EVENT_MASK Чтобы обработать событие, следует заменить соответствующий метод одного из ваших суперклассов. Удостоверьтесь также, что вызвали версию суперкласса метода. В табл. 25.3 перечислены некоторые наиболее часто используемые методы и классы, которые их предлагают. Таблица 25.3. Методы обработки событий Методы обработки ; Button p r o c e s s A c t i o n E v e n t () Checkbox p r o c e s s I t e m E v e n t () Che с kboxMenu11 em p r o c e s s I t e m E v e n t () Choice p r o c e s s I t e m E v e n t () Component p r o c e s s C o m p o n e n t E v e n t (),p r o c e s s F o c u s E v e n t (), pro- c e s s K e y E v e n t (), p r o c e s s M o u s e E v e n t (),processMouseMo- t i o n E v e n t (), p r o c e s s M o u s e W h e e l E v e n t () List p r o c e s s A c t i o n E v e n t (), p r o c e s s I t e m E v e n t () Menultem p r o c e s s A c t i o n E v e n t () Scrollbar p r o c e s s A d j u s t m e n t E v e n t () TextComponent p r o c e s s T e x t E v e n t (В следующих разделах будут представлены простые программы, демонстрирующие расширение компонентов Расширение класса B u t t o В приведенной ниже программе создается аплет, который отображает кнопку сметкой" (Тестовая кнопка. Если щелкнуть на этой кнопке, в строке состояния средства просмотра аплетов или браузера будет выведена строка " ас - tion event " (событие действия, за которой последует номер нажатой кнопки. Программа содержит один класс верхнего уровня ButtonDemo2, который расширяет класс Applet. В коде определяется статическая целочисленная переменная i, которой присваивается нулевое значение. Она регистрирует количество щелчков на кнопке. Метод init ( ) реализует класс MyButton и добавляет его в аплет. 8 3 2 Часть II. Библиотека Класс MyButton является внутренним классом, расширяющим класс Button. Его конструктор использует параметр super для передачи метки кнопки конструктору суперкласса. Он вызывает метод enableEvents () , поэтому события действия могут быть получены данным объектом. Когда происходит событие действия, вызывается метод processActionEvent () . Этот метод отображает текст в строке состояния и вызывает метод progressActionEvent () для супер класса. Поскольку класс MyButton является внутренним, он может напрямую обращаться к методу showStatus () класса ButtonDemo2. /* * * */ import java.awt.*; import j a v a .a w t .e v e n t .*; import j a v a .a p p l e t .*; public class ButtonDemo2 extends Applet { M y Bu tto n m y B u t t o n ; static int i = 0; public void i n i t () { my Bu t to n = ne w M y B u t t o n ("Test Button"); a d d ( m y B u t t o n ) ; } class My Bu t to n extends Button { public M y B u t t o n (String label) { s u p e r (l a b e l ); e n a b l e E v e n t s ( A W T E v en t .A C TI O N_ E VE N T_ M A SK ) ; } p r o te c te d voi d pr o ce s sA c ti o nE ven t(A cti onE ven t ae) { s h o w S t a t u s ("action event: " + i + + ) ; s u pe r .p r oc e s s A c t i o n E v e n t ( a e ) Расширение класса C h e c k b o В следующей программе создается аплет, который отображает три флажка с метками " 11 еш 1" , " 11 еш 2 " и " 11 em 3 " . При установке или сбросе флажка строка, содержащая имя и состояние этого флажка, будет отображаться в строке состояния средства просмотра аплетов или браузера. Программа содержит один класс верхнего уровня CheckboxDemo2, который расширяет класс Applet. Его метод init () создает три экземпляра класса My Checkbox и добавляет их в аплет. Класс My Checkbox является внутренним классом, расширяющим класс Checkbox. Его конструктор использует параметр super для передачи метки флажка конструктору суперкласса. Он вызывает метод en ableEvents () , так что события пунктов меню могут быть получены этим объектом. Если происходит событие пункта, вызывается метод processItemEvent (). Этот метод отображает текст в строке состояния и вызывает метод processIte mEvent () для суперкласса. /* * * */ import j a v a .a w t .*; import j a v a .a w t .event.*; Глава 25. Использование элементов управления, диспетчеров компоновки. 8 3 3 import java.applet.*; public class CheckboxDemo2 extends Applet { MyCheckbox myCheckboxl, myCheckbox2, myCheckbox3; public void i n i t () { myCheckboxl = new MyCheckbox("Item 1"); // myCheckboxl = new Элемент 1") ; add(myCheckboxl); myCheckbox2 = new MyCheckbox("Item 2"); // myCheckbox2 = new Элемент 2"); add(myCheckbox2); myCheckbox3 = new MyCheckbox("Item 3"); // myCheckbox3 = new Элемент 3"); add(myCheckbox3); } class MyCheckbox extends Checkbox { public MyCheckbox(String label) { super(label); enableEvents(AWTEvent.ITEM_EVENT_MASK); } protected void processItemEvent(ItemEvent ie) { showStatus("Checkbox name/state: " + getLabel() + "/ " + getState()); // showStatus("Имя/состояние флажка " + getLabel() + I I "/ " + Расширение группы флажков Приведенная ниже программа является модификацией предыдущего примера с флажком. На этот раз группу флажков формируют несколько флажков. Таким образом, водно и тоже время можно установить только один флажок */ import j a v a .a w t .*; import j a v a .a w t .event.*; import java.applet.*; public class CheckboxGroupDemo2 extends Applet { CheckboxGroup cbg; MyCheckbox myCheckboxl, myCheckbox2 , myCheckbox3; public void init() { cbg = new CheckboxGroup(); myCheckboxl = new MyCheckbox("Item 1", cbg, true); add(myCheckboxl); myCheckbox2 = new MyCheckbox("Item 2", cbg, false); add(myCheckbox2); myCheckbox3 = new MyCheckbox("Item 3", cbg, false); add(myCheckbox3); } class MyCheckbox extends Checkbox { public MyCheckbox(String label, CheckboxGroup cbg, boolean flag) { super(label, cbg, flag); 2 7 3ak 3030 8 3 Часть II. Библиотека Java enableEvents(AWTEvent.ITEM_EVENT_MASK); } protected void processItemEvent(ItemEvent ie) { showStatus("Checkbox name/state: " + getLabel() + "/" + getState()); Расширение класса C h o i c В следующей программе создается аплет, который отображает список выбора с пунктами, имеющими метки "Red", "Green" и "Blue". При выделении пункта в строке состояния средства просмотра аплетов или браузера отображается текст, содержащий название цвета. Имеется один класс верхнего уровня C h o i c e D e m o 2, который расширяет класс App l e t . Его метод in i t () создает элемент выбора и добавляет его к аплету. Класс M y C h o i c e является внутренним классом, который расширяет класс Choice. Он вызывает метод e n a b l e E v e n t s () , чтобы этот объект мог получать извещения о событиях пунктов. Когда происходит событие элемента, вызывается метод p r o c e s s I t e m E v e n t () . Этот метод отображает текст в строке состояния и вызывает метод p r o c e s s I t e m E v e n t () для суперкласса. /* * * */ import java.awt.*; import java.a w t .event.*; import java.applet.*; public class ChoiceDemo2 extends Applet { MyChoice choice; public void in i t () { choice = new MyChoice(); choice.a d d ("Red"); choice.a d d ("Green"); choice.a d d ("Blue"); add(choice) ; } class MyChoice extends Choice { public MyChoice() { enableEvents(AWTEvent.ITEM_EVENT_MASK); } protected void processItemEvent(ItemEvent ie) { showStatus("Choice selection: " + getSelectedltem()); // Состояние выбора " + getSelectedltem()); Расширение класса L i s Приведенная ниже программа является модификацией предыдущего примера, но только вместо меню выбора используется список. Существует один класс верхнего уровня ListDemo2, который расширяет класс Applet. Его метод init () создает элемент списка и добавляет его к аплету. Класс MyList является внутренним клас Глава 25. Использование элементов управления, диспетчеров компоновки. 8 3 сом, расширяющим класс List. Он вызывает метод enableEvents () , так что этот объект может получать извещения о событии действия и элемента. Если установить или сбросить отметку с элемента, будет вызван метод processItemEvent () . При двойном щелчке на элементе вызывается также метод processActionEvent ( Оба метода отображают строку, после чего передают управление суперклассу /* * * */ import j a v a .a w t .*; import j a v a .a w t .event.*; import java.applet.*; public class ListDemo2 extends Applet { MyList list; public void i n i t () { list = new M y L i s t (); list.a d d ("Red"); list.a d d ("Green"); list.a d d ("Blue"); a d d (list); } class MyList extends List { public M y L i s t () { enableEvents(AWTEvent.ITEM_EVENT_MASK I AWTEvent.ACTION_EVENT_MASK) ; } protected void processActionEvent(ActionEvent ae) { showStatus("Action event: " + a e .getActionCommand()); // Событие действия " + a e .getActionCommand()); super.processActionEvent(ae); } protected void processItemEvent(ItemEvent ie) { showStatus("Item event: " + getSelectedltem()); Расширение класса S c r o l l b a В следующей программе создается аплет, который отображает полосу прокрутки. При работе с этим элементом управления в строке состояния средства просмотра аплетов или браузера отображается строка, которая включает значение, представляемое полосой прокрутки. Имеется только один класс верхнего уровня S c r o l lbarD em o2, который расширяет класс A p p le t. Его метод i n i t () создает полосу прокрутки и добавляет ее к аплету. Класс M y S c ro llb a r является внутренним классом, расширяющим класс S c r o l l b a r . Он вызывает метод e n a b le E v e n ts (), так что этот объект может получать извещения о событиях настройки. При работе с полосой прокрутки вызывается метод р го, а при выборе элемента — метод p ro c e s s A d ju s tm e n tE - v e n t (). Он отображает строку, после чего передает управление суперклассу. /* * * */ import j a v a .a w t .*; import j a v a .a w t .event.*; 8 3 Часть II. Библиотека Java import java.applet.*; public class ScrollbarDemo2 extends Applet { MyScrollbar myScrollbar; public void init() { myScrollbar = new MyScrollbar(Scrollbar.HORIZONTAL, 0, 1, 0, 100); myScrollbar.setPreferredSize(new Dimension(100, 20)); add(myScrollbar); } class MyScrollbar extends Scrollbar { public MyScrollbar(int style, int initial, int thumb, int min, int max) { super(style, initial, thumb, min, m a x ) ; enableEvents(AWTEvent.ADJUSTMENT_EVENT_MASK); } protected void processAdjustmentEvent(AdjustmentEvent ae) { showStatus("Adjustment event: " + a e .getValue()); // Событие настройки " + a e .getValue()); setValue(getValue()); Несколько слово переопределении метода paint() Прежде чем завершить изучение элементов управления библиотеки AWT, скажем несколько слово переопределении метода paint (). Хотя в этой книге не было представлено достаточно простых примеров применения библиотеки AWT с переопределением метода paint () , бывают ситуации, когда необходим вызов реализации метода paint () суперкласса. Поэтому для некоторых программ вы должны будете использовать следующий шаблон метода paint (). public void paint(Graphics g) { // код перерисовки данного окна Вызов метода p a i n t () суперкласса В языке Java есть два общих типа компонентов тяжеловесные (heavyweight ) и легковесные (lightweight). У тяжеловесных компонентов есть собственное базовое окно. Легковесный компонент полностью реализуется в коде Java и использует окно, предоставленное родителем. Все элементы управления AWT, описанные и используемые в этой главе, являются тяжеловесными. Но если контейнер содержит какие-нибудь легковесные компоненты (те. имеет дочерние легковесные компоненты, ваше переопределение метода paint () для этого контейнера должно вызвать метод super paint (). При вызове метода super paint () вы гарантируете правильность перерисовки любых легковесных дочерних компонентов, таких как легковесные элементы управления. Если вы не уверены в типе дочернего компонента, то для выяснения можете вызвать метод isLightweight ( ), определенный в классе Component. Он возвращает значение true, если компонент легковесный, и значение false — в противном случае ГЛАВА ^Р^фг^. v - 4 -l# # lb * Ш J. Ы «£.. Ш ■ Изображения В этой главе будет рассмотрен класс Image библиотеки AWT и пакет java. awt image. Вместе они обеспечивают поддержку воспроизведения изображений, которое заключается в отображении графических изображений и манипулировании ими. Изображением является обычный прямоугольный графический объект. В веб-проектировании изображения являются ключевым компонентом. Когда в 1993 году разработчики из NCSA (National Center for Supercom puter Applications — Национальный центр по применению суперкомпьютеров) решили включить дескриптор в браузер Mosaic, это способствовало быстрому развитию системы веб. Этот дескриптор использовался для встраивания изображения в поток гипертекста. Язык Java расширяет этот базовый принцип, позволяя программно управлять изображениями. Благодаря этой важной особенности, Java обеспечивает всестороннюю поддержку воспроизведения изображений. Изображения представляют собой объекты класса Image, который является частью пакета j ava. awt. Манипулирование изображениями осуществляется с помощью классов пакета j ava. awt. image, который содержит большое количество классов воспроизведения изображений и интерфейсов. Не имея возможности рассмотреть каждый класс и интерфейс, мы сосредоточимся на тех из них, которые участвуют в основном процессе воспроизведения изображений. Ниже перечислены классы пакета j ava. awt. image, которые будут рассмотрены в этой главе r y I m a g e S o u r се FilteredlmageSource PixelGrabber ImageFilter RGBImageFilter Мы будем применять следующие интерфейсы. ImageConsumer ImageObserver ImageProducer Также в главе рассматривается класс MediaTracker, который является частью пакета j ava. Форматы файлов Первоначально веб-изображения могли быть представлены только в формате GIF. Формат изображений GIF был разработан специалистами из компании CompuServe в 1987 году для обеспечения просмотра изображений в оперативном режиме, поэтому его удобно было использовать и для Интернета. Каждое изображение GIF может содержать не более 256 цветов. В связи с этим ограничением, в 1995 году ведущие разработчики браузеров включили поддержку изображений JPEG. Формат JPEG был разработан группой специалистов-фотографов для хранения псевдополутоновых изображений с полным спектром цветов. Если правиль- 8 3 Часть II. Библиотека но сформировать подобное изображение, то оно будет передавать более высокую степень точности и его можно будет сжимать более компактно, чем аналогичное изображение в формате GIF. Другим форматом файла является PNG. Это тоже разновидность формата GIF. Как правило, в своих программах вам не придется решать, какой формат нужно использовать. Классы изображений Java абстрагируют все различия между форматами благодаря безупречному интерфейсу. Основы работы с изображениями создание загрузка и отображение В процессе работы с изображениями выбудете выполнять, в основном, три операции создание изображения, его загрузка и отображение. Чтобы обратиться к изображениям, которые хранятся в памяти, а также к изображениям, которые необходимо загрузить из внешних источников данных, в языке Java используется класс Image. Таким образом, Java обеспечивает способы создания нового объекта изображения и способы его загрузки. Помимо этого, Java предлагает функциональные средства, позволяющие отображать изображения. Все это мы рассмотрим прямо сейчас. Создание объекта класса i m a g Могло показаться, что для создания изображения в памяти требуется примерно такая строка test = new Image(200, 100); // Ошибка — не будет работать Однако это не так. Любое изображение предназначено для того, чтобы его можно было отобразить на экране монитора, а класс Image не располагает достаточным количеством информации об условиях, необходимых для создания подходящего формата данных для экрана. Поэтому класс Component пакета j a v a . awt включает метбд create Image () , используемый для создания объектов класса Image. Имейте ввиду, что все компоненты AWT являются подклассами класса Component, поэтому каждый из них поддерживает данный метод.) Метод create Image () имеет следующие две формы createlmage(ImageProducer производИ зображ ения) Image createlmage(int ширина int высота ) В первом случае возвращается изображение, созданное с помощью производителя (параметр производИ зображ ения), который представляет собой объект класса, реализующий интерфейс ImageProducer. О производителях изображений поговорим чуть позже) Во втором случае возвращается пустое изображение, имеющее определенную ширину и высоту. Ниже показан его пример с = new Canvas(); Image test = с .createlmage(200, Здесь для формирования объекта класса Image будет создан экземпляр класса Canvas и вызван метод createlmage () . Пока что изображение остается пустым. Позже вы увидите, как можно записать в него данные. Загрузка изображения Чтобы получить определенное изображение, его можно также загрузить. Для этого служит метод get Image () , определенный в классе Applet. Он имеет следующие формы Глава 26. Изображения 8 3 9 Image getImage(URL u r i) Image getImage(URL u r i , String имяИзображения) В первом случае будет возвращен объект класса Image, который инкапсулирует изображение, хранящееся по адресу, определяемому в параметре uri. Во втором случае будет возвращен объект класса Image, инкапсулирующий изображение, адрес и имя которого определяются параметрами uri и имяИзображения соот ветственно. Отображение изображения После того как получите изображение, его можно будет отобразить с помощью метода drawlmage () , который является членом класса Graphics. Этот метод имеет несколько форм. Ниже представлена форма, которая используется в настоящей книге drawlmage(Image объектИзображения, int слева сверху объектИзображения) В этом случае будет отображено изображение, передаваемое при помощи параметра объектИзображения; верхний левый угол изображения определяют параметры слева и сверху Параметр объектИзображения представляет ссылку на класс, который реализует интерфейс ImageObserver. Этот интерфейс реализуют все компоненты библиотеки. Наблюдатель изображения представляет собой объект, который может вести наблюдение за изображением вовремя его загрузки. Интерфейс ImageObserver рассмотрим в следующем разделе. Загрузить и отобразить изображение с помощью методов g e t Image () и d raw - I n a g e () несложно. Ниже показан пример аплета, который загружает и отображает отдельное изображение. В этом аплете загружается файл S e a t t l e . jp g , однако для данного примера можете взять любой другой файл формата GIF, JPG или PNG (при условии, что он будет находиться в том же каталоге, что и файл HTML, содержащий аплет). /* * * * */ import j a v a .a w t .*; import java.applet.*; public class SimplelmageLoad extends Applet { Image img; public void init() { img = getlmage(getDocumentBase(), getParameter("img")); } public void paint(Graphics g) { g .drawlmage(img, 0, 0, В методе init() переменной img присваивается изображение, возвращенное методом get Image (). Метод get Image () использует строку, возвращенную методом getParameter (" img" ), в качестве имени файла с изображением. Это изображение загружается из URL, который связан с результатом выполнения метода getDocumentBase () , те. URL страницы HTML, в которой находился этот 8 4 Часть II. Библиотека дескриптор аплета. Имя файла, возвращенное методом g e t P a r a m e t e r ( " im g " ), получено из дескриптора аплета < param nam e= " img" v a l u e = " S e a t t l e .j p g " >. Такая схема эквивалентна применению дескриптора HTML < img s c r = " S e a t t l e . jp g " w id th = 2 4 8 h e ig h t= 1 4 6 > , хотя она работает немного медленнее. На рис. 26.1 можно видеть результат выполнения этой программы. Рис. 26.1. Результат выполнения программы Выполнение этого аплета начинается с загрузки изображения img в методе init () . На экране монитора выбудете видеть изображение в процессе егоза грузки из сети, поскольку при реализации интерфейса ImageObserver классом Applet метод paint () вызывается каждый раз при поступлении новых данных, связанных с изображением. Конечно, неплохо иметь возможность наблюдать заходом загрузки изображения, однако будет лучше, если время, отводимое на загрузку изображения, вы потратите на параллельное выполнение других задач. Это позволит отобразить полностью сформированное изображение на экране монитора мгновенно сразу же после его загрузки. Интерфейс ImageObserver, о котором пойдет речь далее, можно применять для наблюдения заходом загрузки изображения в момент вывода на экран монитора какой-то другой информации. И н тер фей с I m a g e O b s e r v e Описываемый интерфейс используется для получения уведомления о формировании изображения он определяет только один метод — imageUpdate (). Используя наблюдатель изображений, вы сможете выполнять ряд других действий — отображать индикатор процесса выполнения или, к примеру, переключаться на экран при получении уведомления о ходе процесса загрузки. Этот тип уведомлений полезен при загрузке изображения по низкоскоростной сети. Метод imageUpdate () имеет следующую общую форму imageUpdate(Image объектИзображения, int флаги слева сверху ширина int высота ) Здесь параметр объектИзображения представляет загружаемое изображение, а параметр флаги — целое число, которое показывает состояние обновляемого отчета. Четыре целочисленных параметра, слева сверху ширина и высота, определяют прямоугольник, значения которого зависят от значений, передаваемых в параметре флаги Метод imageUpdate () возвращает значение false, если Глава 26. Изображения 8 4 процесс загрузки был завершен, и значение true — если необходимо обработать еще одно изображение. Параметр флаги содержит один или несколько битовых флагов, определяемых как статические переменные в рамках интерфейса ImageObserver. Эти флаги, а также передаваемая сих помощью информация представлены в табл. Таблица 26.1. Битовые флаги параметра флаги метода imageUpdate () li a r ^ 4 ‘ T — НааМчение Параметр ширина является действительными содержит значение ширины изображения HEIGHT Параметр высота является действительными содержит значение высоты изображения PROPERTIES Свойства, связанные с изображением, можно получить с помощью метода i m g O b j .g e t P r o p e r t y (Были получены дополнительные пиксели, необходимые для рисования изображения. Параметры слева, сверху, ширина и высота определяют прямоугольник, содержащий новые пиксели FRAMEBITS Был получен весь кадр, являющийся частью ранее нарисованного много кадрового изображения. Этот кадр можно отобразить. Параметры с лева, сверху, ширина и высота не используются ALLBITS Изображение готово. Параметры слева, сверху, ширина и высота не используются ERROR Обнаружена ошибка в изображении, за которым велось асинхронное наблюдение. Изображение неготово и не может быть отображено. Не получено никакой дополнительной информации об изображении. Будет установлен также флаг ABORT, чтобы показать, что процесс формирования изображения был прерван ABORT Формирование изображения, за которым велось асинхронное наблюдение, было прервано до того, как оно было полностью готово. Однако если не было ошибки, то при попытке обращения к какой-либо части данных изображения начнется повторное формирование изображения Класс Applet имеет реализацию метода imageUpdate () согласно интерфейсу ImageObserver, который используется для перерисовки изображений вовремя их загрузки. Вы можете изменить это поведение, если переопределите данный метод в своем классе. Ниже показан пример применения метода imageUpdate (). public boolean imageUpdate(Image img, int flags, int x, int y, int w, int h) { if ((flags Sc ALLBITS) == 0) { System.out.println("Still processing the image."); // Изображение все еще обрабатывается return true; } else { System.out.println("Done processing the image."); // System.o u t Обработка изображения завершена return false; } } 8 4 Часть II. Библиотека Двойная буферизация Изображения можно использовать не только для хранения картинок и рисунков, как было показано только что, но ив качестве внеэкранных поверхностей рисования. Сих помощью можно визуализировать любое изображение, включая текст и графику во внеэкранном буфере, содержимое которого можно будет отобразить через некоторый промежуток времени. Преимущество такого подхода заключается в том, что изображение можно будет увидеть лишь после того, как оно будет полностью готово. Для рисования сложной поверхности может потребоваться несколько миллисекунд или более, причем для пользователя этот процесс может выглядеть как серия вспышек или мерцаний. Подобные эффекты отвлекают внимание и приводят к тому, что пользователь воспринимает визуализируемое изображение гораздо медленнее, чем это происходит на самом деле. Процесс использования внеэкранного изображения для уменьшения мерцания называется двойной буфершацгьей, поскольку экран монитора принимается в качестве буфера для пикселей, а внеэкранное изображение является вторым буфером, в котором можно подготавливать пиксели для визуализации. Вы уже видели в этой главе, как создается пустой объект класса Image. Сейчас будет показано, как осуществляется рисование изображения на самом экране. Если вы помните из предыдущих глав, для этой цели нужен объект класса G ra p h ic s , благодаря которому можно будет использовать любые методы визуализации, доступные в Java. Он удобен тем, что доступ к объекту класса G ra p h i с s , который можно применять для рисования изображения, осуществляется с помощью метода g e t G r a p h ic s (). Ниже показан фрагмент кода, в котором создается новое изображение, принимается графическое содержимое и все изображение заполняется красными пикселями. Canvas с = new Canvas(); Image test = с .createlmage(200, 100); Graphics gc = tes t .getGraphics(); g c .setColor(Color.red) ; gc.fillRect(0, 0, 200, После того как создадите и заполните внеэкранное изображение, его видно не будет. Чтобы отобразить искомое изображение, вызовите метод d raw lm a g e (). Ниже показан пример, в котором для рисования изображения требуется много времени. Вы сможете сравнить, как двойная буферизация влияет на восприятие времени рисования * */ import j a v a .a w t .*; import j a v a .a w t .event.*; import java.applet.*; public class DoubleBuffer extends Applet { int gap = 3; int mx, my; boolean flicker = true; Image buffer = null; int w, h; public void in i t () { Dimension d = getSize(); w = d.width; h = d.height; Глава 26. Изображения 8 4 3 buffer = createlmage(w, h ) ; addMouseMotionListener(new MouseMotionAdapter() public void mouseDragged(MouseEvent me) { mx = m e .g e t X (); my = m e .g e t Y (); flicker = false; repaint(); } public void mouseMoved(MouseEvent me) { mx = m e .g e t X () , my = m e .g e t Y () , flicker = true; repaint(); } }) ; } public void paint(Graphics g) { Graphics screengc = null; if ( !flicker) { screengc = g; g = buffer.getGraphics(); } g .setColor(Color.blue); g . fillRect(0, 0, w, h ) ; g .setColor(Color.red); for (int i=0; i g .drawLine(i , 0, w-i, h ) ; for (int i=0; i |