Наши партнеры

UnixForum





Библиотека сайта rus-linux.net

Фреймворк Violet

Глава 22 из книги "Архитектура приложений с открытым исходным кодом", том 1.

Оригинал: "Violet", глава из книги "The Architecture of Open Source Applications"
Автор: Cay Horstmann
Перевод: Н.Ромоданов

22.6. Java 2D

В Violet интенсивно используется библиотека Java2D, один из менее известных драгоценных камней в Java API. Каждый узел и ребро имеет метод getShape, который выдает java.awt.Shape - общий интерфейс всех форм Java2D. В этом интерфейсе реализованы прямоугольники, круги, пути и их объединения, пересечения и разности. Класс GeneralPath используется для создания фигур, которые состоят из сегментов произвольных линий и квадратичных/кубических кривых, например, прямых и закругленных стрелок.

Чтобы оценить гибкость Java2D API, рассмотрим следующий код, рисующий тени в методе AbstractNode.draw:

Shape shape = getShape();
if (shape == null) return;
g2.translate(SHADOW_GAP, SHADOW_GAP);
g2.setColor(SHADOW_COLOR);
g2.fill(shape);
g2.translate(-SHADOW_GAP, -SHADOW_GAP);
g2.setColor(BACKGROUND_COLOR);
g2.fill(shape);

Несколько строк кода создают тени для любых форм, даже для тех, которые разработчик может добавить на более позднем этапе.

Конечно, в Violet сохраняются растровые изображения в любом формате, который поддерживается пакетом javax.imageio; то есть, GIF, PNG, JPEG, и так далее. Когда мой издатель спросил меня о векторных изображениях, я обнаружил еще одно преимущество библиотеки Java 2D. При печати на PostScript-принтере, Java2D операции преобразуются в операции векторной графики на языке PostScript. Если печатать в файл, результат можно использовать с такими программами, как ps2eps, а затем его можно импортировать в Adobe Illustrator или Inkscape. В следующем коде компонент comp из Swing, метод которого paintComponent используется для рисования графа:

DocFlavor flavor = DocFlavor.SERVICE_FORMATTED.PRINTABLE;
String mimeType = "application/postscript";
StreamPrintServiceFactory[] factories;
StreamPrintServiceFactory.lookupStreamPrintServiceFactories(flavor, mimeType);
FileOutputStream out = new FileOutputStream(fileName);
PrintService service = factories[0].getPrintService(out);
SimpleDoc doc = new SimpleDoc(new Printable() {
  public int print(Graphics g, PageFormat pf, int page) {
      if (page >= 1) return Printable.NO_SUCH_PAGE;
      else {
        double sf1 = pf.getImageableWidth() / (comp.getWidth() + 1);
        double sf2 = pf.getImageableHeight() / (comp.getHeight() + 1);
        double s = Math.min(sf1, sf2);
        Graphics2D g2 = (Graphics2D) g;
        g2.translate((pf.getWidth() - pf.getImageableWidth()) / 2,
            (pf.getHeight() - pf.getImageableHeight()) / 2);
        g2.scale(s, s);

        comp.paint(g);
        return Printable.PAGE_EXISTS;
      }
  }
}, flavor, null);
DocPrintJob job = service.createPrintJob();
PrintRequestAttributeSet attributes = new HashPrintRequestAttributeSet();
job.print(doc, attributes);

В начале, я был обеспокоен тем, что использование общих форм может привести к снижению производительности, но, как оказалось, это не так. Операция вырезания фрагментов работает достаточно хорошо, поскольку в действительности выполняются только те операции, которые необходимы для обновления текущей видимой области.


Продолжение статьи: 22.7. Это не фреймворк приложений Swing.