页面解析完成后,需要等到所有图片都加载完毕后才能布局组件。
拦截所有图像加载以确保在布局组件之前完全加载所有图像。我通过覆盖 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。也许有更简单的方法。