Microsoft Visual J++. Создание приложений и аплетов на языке Java. Часть 2© Александр Фролов, Григорий ФроловТом 32, М.: Диалог-МИФИ, 1997, 288 стр. Приложение RectanglesВ предыдущем приложении задача выполняла периодическую перерисовку окна аплета, вызывая из метода run метод repaint. Такая методика приводит к сильному мерцанию окна аплета и поэтому во многих случаях нежелательна. Приложение Rectangles, постоянно отображающее в своем окне прямоугольники случайного размера, расположения и цвета (рис. 1.2), использует другой способ. Оно запускает задачу, которая рисует в окне аплета непосредственно. Рис. 1.2. Окно аплета Rectangles В результате в каждый момент времени перерисовывается только часть окна аплета и мерцание отсутствует. Исходные тексты приложенияИсходный файл приложения Rectangles приведен в листинге 1.3. Листинг 1.3. Файл Rectangles\Rectangles.java // ========================================================= // Рисование прямоугольников в отдельной задаче // // (C) Фролов А.В, 1997 // // E-mail: frolov@glas.apc.org // WWW: http://www.glasnet.ru/~frolov // или // http://www.dials.ccas.ru/frolov // ========================================================= import java.applet.*; import java.awt.*; import java.util.*; public class Rectangles extends Applet implements Runnable { // Ссылка на задачу рисования прямоугольников Thread m_Rectangles = null; // ------------------------------------------------------- // getAppletInfo // Метод, возвращающей строку информации об аплете // ------------------------------------------------------- public String getAppletInfo() { return "Name: Rectangles\r\n" + "Author: Alexandr Frolov\r\n" + "E-mail: frolov@glas.apc.org" + "WWW: http://www.glasnet.ru/~frolov" + "Created with Microsoft Visual J++ Version 1.0"; } // ------------------------------------------------------- // paint // Метод paint, выполняющий рисование в окне аплета // ------------------------------------------------------- public void paint(Graphics g) { // Определяем текущие размеры окна аплета Dimension dimAppWndDimension = size(); // Выбираем в контекст отображения желтый цвет g.setColor(Color.yellow); // Закрашиваем внутреннюю область окна аплета g.fillRect(0, 0, dimAppWndDimension.width - 1, dimAppWndDimension.height - 1); // Выбираем в контекст отображения черный цвет g.setColor(Color.black); // Рисуем рамку вокруг окна аплета g.drawRect(0, 0, dimAppWndDimension.width - 1, dimAppWndDimension.height - 1); } // ------------------------------------------------------- // start // Метод вызывается при первом отображении окна аплета // ------------------------------------------------------- public void start() { if (m_Rectangles == null) { m_Rectangles = new Thread(this); m_Rectangles.start(); } } // ------------------------------------------------------- // start // Метод вызывается при первом отображении окна аплета // ------------------------------------------------------- public void stop() { if (m_Rectangles != null) { m_Rectangles.stop(); m_Rectangles = null; } } // ------------------------------------------------------- // run // Метод, который работает в рамках отдельной задачи // Он рисует в окне аплета прямоугольники случайного // цвета, размера и расположения // ------------------------------------------------------- public void run() { // Получаем контекст отображения для окна аплета Graphics g = getGraphics(); // Определяем текущие размеры окна аплета Dimension dimAppWndDimension = size(); while (true) { int x, y, width, height; int rColor, gColor, bColor; // Выбираем случайным образом размеры // и расположение рисуемого прямоугольника x = (int)(dimAppWndDimension.width * Math.random()); y = (int)(dimAppWndDimension.height * Math.random()); width = (int)(dimAppWndDimension.width * Math.random()) / 2; height = (int)(dimAppWndDimension.height * Math.random()) / 2; // Выбираем случайный цвет для // рисования прямоугольника rColor = (int)(255 * Math.random()); gColor = (int)(255 * Math.random()); bColor = (int)(255 * Math.random()); // Устанавливаем выбранный цвет // в контексте отображения g.setColor(new Color(rColor, gColor, bColor)); // Рисуем прямоугольник g.fillRect(x, y, width, height); // Выполняем задержку на 50 миллисекунд try { Thread.sleep(50); } catch (InterruptedException e) { stop(); } } } // ------------------------------------------------------- // mouseEnter // Метод вызывается, когда курсор мыши оказывается над // окном аплета // ------------------------------------------------------- public boolean mouseEnter(Event evt, int x, int y) { if (m_Rectangles != null) { // Когда курсор мыши оказывается над поверхностью // окна аплета, временно приостанавливаем // задачу рисования прямоугольников m_Rectangles.suspend(); } return true; } // ------------------------------------------------------- // mouseExit // Метод вызывается, когда курсор мыши покидает // окно аплета // ------------------------------------------------------- public boolean mouseExit(Event evt, int x, int y) { if (m_Rectangles != null) { // Когда курсор мыши покидает окно аплета, // возобновляем работу задачи рисования // прямоугольников m_Rectangles.resume(); } return true; } } В листинге 1.4 находится исходный текст документа HTML, созданного автоматически для нашего аплета. Листинг 1.4. Файл Rectangles\Rectangles.html <html> <head> <title>Rectangles</title> </head> <body> <hr> <applet code=Rectangles.class id=Rectangles width=320 height=240 > </applet> <hr> <a href="Rectangles.java">The source.</a> </body> </html> Описание исходных текстовДля создания задачи аплет Rectangles реализует интерфейс Runnable, то есть использует второй из описанных нами методов, как и предыдущий аплет. Ниже мы рассмотрим наиболее важные методы аплета Rectangles. Метод paintВ предыдущем приложении метод paint периодически получал управление в результате периодического вызова метода repaint, выполняемого отдельной задачей. Метод paint аплета Rectangles вызывается только при инициализации и тогда, когда нужно обновить окно аплета. Этот метод определяет текущие размеры окна аплета, закрашивает окно желтым цветом и рисует вокруг окна черную рамку. Метод startКогда пользователь начинает просмотр документа HTML, содержащего наш аплет, метод start создает и запускает задачу. Для создания задачи мы используем оператор new, а для старта задачи - метод start класса Thread: public void start() { if (m_Rectangles == null) { m_Rectangles = new Thread(this); m_Rectangles.start(); } } Обратите внимание, что мы передаем конструктору класса Thread параметр this - ссылку на аплет. В результате роль задачи, работающей параллельно с кодом аплета, будет выполнять метод run, определенный в классе аплета. Ссылка на созданную задачу записывается в поле m_Rectangles. Метод stopМетод stop нашего аплета не имеет никаких особенностей. Он вызывается, когда пользователь покидает страницу сервера Web с аплетом. В этом случае метод останавливает задачу, вызывая для этого метод stop класса Thread: public void stop() { if (m_Rectangles != null) { m_Rectangles.stop(); m_Rectangles = null; } } После остановки в поле m_Rectangles записывается значение null. Это является признаком того, что задача остановлена. Метод runПрограммный код метода run работает в рамках отдельной задачи. Он рисует в окне аплета закрашенные прямоугольники. Прямоугольники имеют случайные координаты, расположение и цвет. Для того чтобы рисовать, необходимо получить контекст отображения. Так как наша задача, точнее, метод run определен в классе аплета, то он может получить контекст отображения, вызвав метод getGraphics: Graphics g = getGraphics(); Для рисования нам также нужно знать размеры окна аплета. Мы получаем эти размеры при помощи метода size: Dimension dimAppWndDimension = size(); Вооружившись контекстом отображения и размерами окна аплета, задача входит в бесконечный цикл рисования прямоугольников. В качестве генератора случайных чисел мы используем метод random из класса Math, который при каждом вызове возвращает новое случайное число типа double, лежащее в диапазоне значений от 0.0 до 1.0. Координаты по осям X и Y рисуемого прямоугольника определяются простым умножением случайного числа, полученного от метода random, соответственно, на ширину и высоту окна аплета: x = (int)(dimAppWndDimension.width * Math.random()); y = (int)(dimAppWndDimension.height * Math.random()); Аналогично определяются размеры прямоугольника, однако чтобы прямоугольники не были слишком крупными, мы делим полученные значения на 2: width = (int)(dimAppWndDimension.width * Math.random())/2; height = (int)(dimAppWndDimension.height * Math.random())/2; Так как случайное число имеет тип double, в обоих случаях мы выполняем явное преобразование результата вычислений к типу int. Для случайного выбора цвета прямоугольника мы вычисляем отдельные цветовые компоненты, умножая значение, полученное от метода random, на число 255: rColor = (int)(255 * Math.random()); gColor = (int)(255 * Math.random()); bColor = (int)(255 * Math.random()); Полученные значения цветовых компонент используются в конструкторе Color для получения цвета. Этот цвет устанавливается в контексте отображения методом setColor: g.setColor(new Color(rColor, gColor, bColor)); Теперь все готово для рисования прямоугольника, которое мы выполняем при помощи метода fillRect: g.fillRect(x, y, width, height); После рисования прямоугольника метод run задерживает свою работу на 50 миллисекунд, вызывая метод sleep: try { Thread.sleep(50); } catch (InterruptedException e) { stop(); } Для обработки исключения InterruptedException, которое может возникнуть во время работы этого метода, мы предусмотрели блок try - catch. При возникновении указанного исключения работа задачи останавливается вызовом метода stop. Метод mouseEnterВ предыдущем томе “Библиотеки системного программиста” мы рассказывали о методах mouseEnter и mouseExit. Первый из этих методов вызывается, когда в результате перемещения курсор мыши оказывается над окном аплета, а второе - когда курсор покидает окно аплета. Мы переопределили эти методы в своем аплете. Когда курсор мыши оказывается над окном аплета, мы временно приостанавливаем работу задачи, вызывая метод suspend: public boolean mouseEnter(Event evt, int x, int y) { if (m_Rectangles != null) { m_Rectangles.suspend(); } return true; } Преостановленная задача не уничтожается. Ее работа может быть продолжена с помощью метода resume. Метод mouseExitКогда курсор мыши покидает окно аплета, вызывается метод mouseExit. Этот метод в нашем аплете возобновляет работу задачи, временно приостановленной методом suspend. Для этого используется метод resume, как это показано ниже: public boolean mouseExit(Event evt, int x, int y) { if (m_Rectangles != null) { m_Rectangles.resume(); } return true; } |