Java/Swing屏幕外渲染(Cobra HTMLPanel->;BuffereImage)问题:组件不存在';我不能先完成重画

Java/Swing屏幕外渲染(Cobra HTMLPanel->;BuffereImage)问题:组件不存在';我不能先完成重画,java,html,paint,jcomponent,cobra,Java,Html,Paint,Jcomponent,Cobra,我正在尝试将Java/Swing的内容呈现为屏幕外的BuffereImage,以便在我的应用程序中的其他地方使用: slideViewPanel.setDocument(document, rendererContext); BufferedImage test = new BufferedImage(300,300,BufferedImage.TYPE_INT_RGB); Graphics g = test.getGraphics(); slideViewPanel.paint(g);

我正在尝试将Java/Swing的内容呈现为屏幕外的BuffereImage,以便在我的应用程序中的其他地方使用:

 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方法只是计划重新呈现文档,但我正在调试程序中单步执行,没有看到第二个线程进行重新呈现。有人了解这里可能发生的情况吗?

尝试调用
g.dispose()
尝试调用
g.dispose()
您必须等待组件可见才能获取图像。 试一试:

   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;
 }

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

   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;
 }

解析页面后,您需要等待所有图像加载完毕,然后再布局组件

截取所有图像加载,以确保在布局组件之前完全加载所有图像。为此,我对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()或框架集

图像绘制是非同步的(绘制可能会中止),因此在使用BuffereImage之前,必须完成所有图像绘制

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

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


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

解析页面后,您需要等待所有图像加载完毕,然后再布局组件

截取所有图像加载,以确保在布局组件之前完全加载所有图像。为此,我对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()或框架集

图像绘制是非同步的(绘制可能会中止),因此在使用BuffereImage之前,必须完成所有图像绘制

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

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


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

实际上,围绕“component.paint(image.getGraphics());”使用“SwingUtilities.invokeAndWait()”命令,如中所示:


实际上,围绕着“component.paint(image.getGraphics());”使用“SwingUtilities.invokeAndWait()”命令,如中所示:

g、 dispose()对不完整的呈现没有帮助,但感谢您指出这一点——API使它听起来像是我应该在图形上下文中使用的东西。查看Cobra文档,看起来“setDocument”调用会安排页面进行渲染,而不是当场渲染。对于“rendering complete”(渲染完成),似乎没有相应的函数/事件通知程序,尽管..g.dispose()对不完整的渲染没有帮助,但感谢您指出这一点--API使它听起来像是我应该在图形上下文中使用的东西。查看Cobra文档,看起来“setDocument”调用会安排页面进行渲染,而不是当场渲染。不过,似乎没有相应的函数/事件通知程序用于“渲染完成”。。