я подготовил код, который будет
Для своего первого примера я подготовил код, который будет работать на платформе Java 1.1. Хотя виртуальные машины JVM 1.2 достаточно распространены, не все могут размещать программы на этой платформе. К сожалению, провайдеры не сильно спешат обновлять виртуальные машины на своих серверах. Как следствие, приходится разрабатывать сервлеты, работающие на платформе Java 1.1. Это не сильно затруднят задачу; тем не менее, есть некоторые сложности, связанные с формированием изображений, которые мы обсудим ниже.
Будем строить круговую диаграмму (pie chart), которую мы, для полноты картины, раскрасим и подпишем. На диаграмме будут изображены напитки, употребляемые разработчиками программного обеспечения. Посмотрим, как можно это сделать.
Для операций ввода/вывода изображений в Java 1.1 Sun предлагает библиотеку Jimi. Sun приобрел ее у небольшой компании. Перед тем, как начать распространять эту библиотеку, компания Sun перенесла классы в пакет com.sun, а в остальном ничего не изменила.
Следующие шаги необходимо проделать для формирования PNG изображения с использованием Jimi.
- Создать окно приложения(Frame для получения изображения.
- Использую AWT изображение, создать реализацию класса Graphics.
- Нарисовать картинку с помощью объекта Graphics.
- Создать объект JimiWriter на основе потока данных, передаваемых клиенту.
- Преобразовать изображение в соответствующий формат и отправить его клиенту.
Для формирования и модификации изображений на платформе Java 1.1 необходимо использовать активную AWT компоненту. Как правило, сервлет не должен создавать AWT компоненты, которые обычно используются в приложениях с графическим интерфейсом пользователя. В этом случае, вам нужен графический (AWT) объект для того, что бы получить объект класса Graphics, с помощью которого можно рисовать новые картинки. Придется смириться с маленьким окошком на консоли Веб сервера. Если вам известны способы создания изображения в Java 1.1 без использования AWT компонент, пожалуйста, сообщите мне. Один из возможных вариантов, загрузить с диска сервера заранее подготовленный шаблон, например методом java.awt.Toolkit.createImage(). После того, как вы создали AWT изображение, вы можете получить реализацию класса Graphics и использовать ее для рисования. Имея в своем распоряжении объект Graphics, вы можете закрыть ненужное окно на консоли сервера. Я оставлю этот эксперимент заинтересованным читателям.
Напомню, что для связи с классом, рисующим круговую диаграмму, сервлет использует интерфейс ImageProducer. Поэтому наш класс JIMIProducer должен реализовывать этот интерфейс. Прежде всего, создадим AWT окно, AWT изображения и, наконец, объект Graphics:
Frame f = new Frame();
f.setVisible(true; image = f.createImage(ImageWidth, ImageHeight); graphics = image.getGraphics(); f.setVisible(false);
Ключевой метод класса JIMIProducer - drawSlice. Получая на входе метку и величину сегмента в градусах, этот метод рисует сегмент диаграммы, раскрашивает его и подписывает. Далее, я расскажу подробней, как это происходит.
Будем заполнять "внутренности" диаграммы по часовой стрелке, начиная с положения "три часа", то есть первую линию проведем из центра к окружности ограничивающей диаграмму в положении часовой стрелки в три часа дня (или ночи, как вам больше нравиться). Отступим по часовой стрелке необходимое количество градусов и нарисуем вторую линию, ограничивающую сегмент диаграммы. И так далее. Приведенный ниже код получает на входе величину сегмента в градусах и рисует границу этого сегмента. Он вызывается последовательно для всех сегментов, при этом предполагается, что в сумме угловые величины составят 360 градусов.
//************************************************* // Преобразуем угол в радианы // 1 градус = pi/180 радиан //************************************************* doubletheta = degrees * (3.14/180); currentTheta += theta;
//************************************************* // Переводим в декартовы координаты // x = r cos @ // y = r sin @ //************************************************* double x = Radius * Math.cos(currentTheta);
double y = Radius * Math.sin(currentTheta);
Point mark2 = newPoint(center); mark2.translate((int)x,(int)y); graphics.drawLine (center.x, center.y, mark2.x, mark2.y);
Затем, нужно раскрасить сегменты диаграммы. Для этого можно воспользоваться очень полезным методом fillArc():
graphics.setColor(colors[colorIndex++]); graphics.fillArc(Inset, Inset, PieWidth, PieHeight, -1 * lastAngle, -1 * degrees);
Последняя задача метода drawSlice() нарисовать метки сегментов. Расположение надписи рассчитывается, основываясь на метрике используемого шрифта. Окончательный вариант диаграммы можно посмотреть на рисунке.
Рис. 1. Окончательный вариант круговой диаграммы. (Не все броузеры показывают файлы формата PNG, поэтому здесь мы поставили GIF файл.)