我正在尝试将Java / Swing Cobra HTML renderer的内容呈现给屏幕外的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方法只是调度文档以进行重新渲染,但我正在调试器中逐步完成,并且我没有看到第二个线程要重新渲染。任何人都对这里可能发生的事情有任何了解吗?
答案 0 :(得分: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。也许有一种更简单的方法。
答案 1 :(得分:0)
尝试拨打g.dispose()
答案 2 :(得分: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;
}
答案 3 :(得分: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 {
}