Внеэкранный рендеринг Java / Swing (Cobra HTMLPanel -> BufferedImage). - PullRequest
1 голос
/ 06 мая 2010

Я пытаюсь отобразить содержимое средства визуализации Java / Swing Cobra HTML в закадровый BufferedImage для использования в другом месте в моем приложении:

 slideViewPanel.setDocument(document, rendererContext);
 BufferedImage test = new BufferedImage(300,300,BufferedImage.TYPE_INT_RGB);
 Graphics g = test.getGraphics();
 slideViewPanel.paint(g);

Полученное изображение в g показывает частично визуализированную страницу - иногда содержимое HTMLFrame до того, как был установлен новый документ; иногда полу-визуализированная версия нового документа. Я понял, что это потому, что метод Cobra setDocument просто планирует документ для повторного рендеринга, но я вхожу в отладчик и не вижу второго потока для повторного рендеринга. Кто-нибудь знает, что здесь может происходить?

Ответы [ 4 ]

1 голос
/ 19 августа 2010

Когда страница была проанализирована, вам нужно подождать, пока все изображения загрузятся, прежде чем выложить компонент.

Перехватить загрузку всех изображений, чтобы убедиться, что все изображения полностью загружены, прежде чем выложить компонент.Я сделал это, переопределив HtmlDocumentImpl.loadImage.(Пришлось создать подкласс DocumentBuilderImpl и переопределить createDocument, чтобы заставить его работать.) Я использовал семафор, чтобы дождаться, пока не станет доступен результат image.getWItdh.

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

Что касается компоновки, существует множество грузовых экспериментов и экспериментов, которые приводят к приведенному ниже фрагменту, так что, возможно, вы можете попытаться удалить некоторые вещи.

            htmlPanel.setVisible(true); 
    htmlPanel.setPreferredWidth(DEFAULT_PAGE_WIDTH);
    logger.info("Calculating preferred size");

    // Get the preferred heigth for the current width.
    Dimension psvz = htmlPanel.getPreferredSize();
    Dimension min = htmlPanel.getMinimumSize();

    logger.info("prf :" + psvz);
    logger.info("min :" + min);

    // Enlarge to the minimum width (with a limit)
    int width = Math.min(MAX_PAGE_WIDTH, Math.max(DEFAULT_PAGE_WIDTH,
            psvz.width));
    int height = psvz.height;

    logger.info("width :" + width);
    logger.info("heigth :" + height);

    htmlPanel.setSize(width, height);

            // actually, htmlPanel is a subclass, and this method exposes validateTree. It may work without it.
    htmlPanel.forceValidateTree(); 

    htmlPanel.doLayout();

    setImageSize(width);
    logger.info("actual size:" + htmlPanel.getSize());

Я не мог понять, что JFrame делает с HtmlPanel, чтобы он правильно рисовал своих детей.Мне пришлось рисовать, используя компонент детей;Т.е. либо htmlPanel.getBlockRenderable (), либо frameset.

Изображения закрашиваются асинхронно (и краски могут прерваться), поэтому перед использованием BufferedImage все изображения должны быть завершены.

Я использовал делегирующий объект graphics2d, переопределяющий все методы рисования изображения, чтобы дождаться завершения рисования.

После этого я обнаружил, что HTML-код может выиграть от изменения макета, поскольку все размеры изображений известныпоэтому я лишаю законной силы компонент и снова выполняю макет и рисование (или на самом деле, я просто вызываю код дважды ...)

После этого можно использовать BufferedImage.Может быть, есть более простой способ.

0 голосов
/ 28 августа 2010

На самом деле, окружите ваш 'component.paint (image.getGraphics ());' с 'SwingUtilities.invokeAndWait ()' как в:

    try {
    SwingUtilities.invokeAndWait(new Runnable() {
        public void run() {
            component.paint(image.getGraphics());
        }
    });
    ImageIO.write(image, "png", file);
} catch (Exception e) {
    } finally {
    }
0 голосов
/ 09 июня 2010

Вам нужно будет подождать, пока компонент станет видимым, чтобы получить изображение.Попробуйте с этим:

   htmlPanel.setDocument(document, rendererContext);
   EventQueue.invokeLater(new Runnable() {
   public void run() {
    if (!captureImage(htmlPanel, "test.jpg")){
     EventQueue.invokeLater(this);
     System.out.println("Encolado");
    }else {
     System.out.println("capturado");
    }
   }
  });

Имея captureImage как:

  public static boolean captureImage(Component component, String fileName) {
  boolean captured = false;
  if (component.isVisible()) {
   Dimension size = component.getSize();
   BufferedImage image = new BufferedImage(size.width, size.height,
     BufferedImage.TYPE_INT_RGB);

   component.paint(image.getGraphics());
   captured = true;
   try {
    ImageIO.write(image, "JPEG", new File(fileName));
   } catch (IOException e) {
    e.printStackTrace();
   }
  }
  return captured;
 }
0 голосов
/ 06 мая 2010

Попробуйте позвонить g.dispose()

...