我可以从JPanel创建BufferedImage而无需在JFrame中呈现吗?

是否可以从JPanel创建BufferedImage而无需先在JFrame中呈现它? 我搜遍了我能想到的任何地方,找不到答案。 有人可以帮忙吗?

这是一些示例代码。 如果我不取消注释JFrame代码,我的BufferedImage是空白的。

test(){ // JFrame frame = new JFrame(); JPanel panel = new JPanel(); Dimension dim = new Dimension(50,50); panel.setMinimumSize(dim); panel.setMaximumSize(dim); panel.setPreferredSize(dim); JLabel label = new JLabel("hello"); panel.add(label); // frame.add(panel); // frame.pack(); BufferedImage bi = getScreenShot(panel); //...code that saves bi to a jpg } private BufferedImage getScreenShot(JPanel panel){ BufferedImage bi = new BufferedImage(panel.getWidth(), panel.getHeight(), BufferedImage.TYPE_INT_ARGB); panel.paint(bi.getGraphics()); return bi; } 

请参阅Swing的 答案 :获取JFrame的图像以及为什么JTable标题没有出现在图像中? 有关绘制尚未渲染的组件的提示。 我希望您的问题的修复程序显示在LabelRenderTest.java的标签中。

 JLabel textLabel = new JLabel(title); textLabel.setSize(textLabel.getPreferredSize()); 

更新

 Dimension dim = new Dimension(50,50); panel.setSize(dim); // very important! panel.setMinimumSize(dim); panel.setMaximumSize(dim); panel.setPreferredSize(dim); // ... 

或者这里是完整的来源。 还需要设置标签的大小。

 import java.awt.Color; import java.awt.Dimension; import java.awt.image.BufferedImage; import javax.swing.*; public class RenderTest { RenderTest() { JPanel panel = new JPanel(); panel.setBackground(Color.RED); Dimension dim = new Dimension(50,50); panel.setSize(dim); panel.setMinimumSize(dim); panel.setMaximumSize(dim); panel.setPreferredSize(dim); JLabel label = new JLabel("hello"); label.setSize(label.getPreferredSize()); panel.add(label); BufferedImage bi = getScreenShot(panel); JOptionPane.showMessageDialog(null, new JLabel(new ImageIcon(bi))); } private BufferedImage getScreenShot(JPanel panel){ BufferedImage bi = new BufferedImage( panel.getWidth(), panel.getHeight(), BufferedImage.TYPE_INT_ARGB); panel.paint(bi.getGraphics()); return bi; } public static void main(String[] args) { new RenderTest(); } } 

编辑2:基本上安德鲁汤普森的答案是正确的,一个框架是没有必要的。 同时拥有一个是实用的,因为对pack()的调用将使布局管理器工作。 我删除了原始答案的第一部分,左边是与记忆相关的部分。 请注意,即使没有帧,仍然需要在Graphics上调用dispose。

关于使用框架时堆空间的用尽:这不应该发生。 可能你完成后只需要在帧上调用dispose() 。 如果这没有帮助,我建议在一个单独的问题中提出这个问题。 从dispose文档:

释放此Window,其子组件及其所有子组件使用的所有本机屏幕资源。 也就是说,这些组件的资源将被销毁,它们使用的任何内存都将返回给操作系统,并且它们将被标记为不可显示。 (…)注意:当处理Java虚拟机(VM)中的最后一个可显示窗口时,VM可能会终止。

编辑:更多的想法:

  • 重用相同的JFrame对象也应该有效。 添加面板,调用包,创建图像,删除面板,重复
  • 不要忘记在你创建的Graphics对象上调用dispose()
  • 在最坏的情况下,您可以不时地从脚本重新启动JVM