如何获得paint / paintComponent生成的图像?
我有一个快速的问题。如何获取由JComponent.paint或者paintComponent生成的图像?
我有一个JComponent,我将其用作"工作区",并且在这里我已经将paintComponent方法重写为自己的方法。事实是,我的工作区JComponent也有子级,它们具有自己的paintComponent方法。
因此,当Swing渲染我的工作区组件时,它先渲染工作区图形,然后再渲染其子级图形。
但是,我想获取我的工作区组件生成的图像(包括工作区图形和子级图形)。
我怎么做?
我试图通过使用自己的Graphics来调用自己的paintComponent / paint-method,但我只是返回了一个黑色图像。这是我尝试过的;
public void paintComponent(Graphics g) { if (bufferedImage != null) { g.drawImage(bufferedImage, 0, 0, this); } else { g.setColor(Color.WHITE); g.fillRect(0, 0, bufferedImage.getWidth(), bufferedImage.getHeight()); } } public BufferedImage getImage() { BufferedImage hello = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB); Graphics g = hello.getGraphics(); paintComponent( g ); return hello; }
欢迎任何想法或者评论! :)
解决方案
如果过早调用getImage,则组件尚未显示,并且宽度和高度仍为0。我们确定要在足够晚的时间打电话吗?尝试将组件的尺寸打印到标准输出,然后查看其尺寸。
好像问题出在BufferedImage的创建上。使用时:
BufferedImage hello = bufferedImage.getSubimage(0,0, getWidth(), getHeight());
相反,它起作用了。我还必须将paintpaint的开关更改为paint以渲染子代。
问题解决了,但是如果有人知道。为什么我的:
BufferedImage hello = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB);
总是渲染黑色图像吗?脱位,但可能很有趣:)
不要从外部调用paintComponent()或者paint()。而是让我们在这些(覆盖)的方法中创建图像。然后,我们可以确保图像将实际包含组件的绘制内容。
这是一个示例应用程序。每次绘制时,ImagePanel实际上都会获取组件的图形内容,这可能会有些浪费,因此我们可能需要调整执行此操作的频率。
public class SomeApp extends JFrame { private static class ImagePanel extends JPanel { private BufferedImage currentImage; public BufferedImage getCurrentImage() { return currentImage; } @Override public void paint(Graphics g) { Rectangle tempBounds = g.getClipBounds(); currentImage = new BufferedImage(tempBounds.width, tempBounds.height, BufferedImage.TYPE_INT_ARGB); super.paint(g); super.paint(currentImage.getGraphics()); } } public SomeApp() { setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); setSize(800,600); int matrixSize = 4; setLayout(new BorderLayout()); add(new JLabel("Wonderful Application"), BorderLayout.NORTH); final ImagePanel imgPanel = new ImagePanel(); imgPanel.setLayout(new GridLayout(matrixSize,matrixSize)); for(int i=1; i<=matrixSize*matrixSize; i++) { imgPanel.add(new JButton("A Button" + i)); } add(imgPanel, BorderLayout.CENTER); final JPanel buttonPanel = new JPanel(); buttonPanel.add(new JButton(new AbstractAction("get image") { @Override public void actionPerformed(ActionEvent e) { JOptionPane.showMessageDialog(SomeApp.this, new ImageIcon(imgPanel.getCurrentImage())); } })); add(buttonPanel, BorderLayout.SOUTH); } public static void main(String[] args) { System.setProperty("swing.defaultlaf", UIManager.getSystemLookAndFeelClassName()); SwingUtilities.invokeLater(new Runnable() { @Override public void run() { new SomeApp().setVisible(true); } }); } }
就像Martijn所说的那样,图像可能是黑色的,因为该组件甚至还没有绘制/显示。我们可以添加一个ComponentListener,使其在显示时得到通知。使用getSubimage的"解决方案"与实际问题无关。我建议我们将其删除。
将新的BufferedImage更改为TYPE_INT_RGB可以为我解决此问题。尽管只是Swing之谜,但我无法给出解释。
public BufferedImage getImage() { BufferedImage hello = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_RGB); Graphics g = hello.getGraphics(); paintComponent( g ); return hello; }