1

我正在尝试将 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

4 回答 4

1

页面解析完成后,需要等到所有图片都加载完毕后才能布局组件。

拦截所有图像加载以确保在布局组件之前完全加载所有图像。我通过覆盖 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() 或框架集。

图像是异步绘制的(并且绘制可能会中止),因此在使用 BufferedImage 之前,必须完成所有图像绘制。

我使用了一个委托 graphics2d 对象来覆盖所有图像绘制方法,以等待绘制完成。

之后,我发现 html 可能会从重新布局中受益,因为所有图像大小都是已知的,所以我使组件无效并再次进行布局和绘画(或者实际上,我只是调用了两次代码......)

之后,可以使用 BufferedImage。也许有更简单的方法。

于 2010-08-19T19:32:30.340 回答
0

试着打电话g.dispose()

于 2010-05-06T18:33:58.753 回答
0

您必须等到组件可见才能获取图像。试试看:

   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;
 }
于 2010-06-09T09:30:56.943 回答
0

实际上,围绕你的 '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 {
    }
于 2010-08-27T20:49:13.960 回答