How do I get the image paint/paintComponent generates?

心不动则不痛 提交于 2019-12-03 15:41:18

If you call getImage too early, your component will not have been displayed yet and will still have a 0 width and height. Have you made sure you're calling it at a sufficient late time? Try printing the component's size to stdout and see what its dimensions are.

Seems like the problem was due to how the BufferedImage was created. When using:

BufferedImage hello = bufferedImage.getSubimage(0,0, getWidth(), getHeight());

Instead it worked. I also had to change switch from paintComponent to paint to render the children.

Problem solved, but if anyone knows. Why did my:

 BufferedImage hello = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB);

Always render a black image? Offtopic, but could be interesting to know :)

Changing the new BufferedImage to TYPE_INT_RGB solves this for me. I can't give an explanation though - just a Swing mystery.

public BufferedImage getImage() {

    BufferedImage hello = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_RGB);
    Graphics g = hello.getGraphics();
    paintComponent( g );

    return hello;
}
jmagica

Do not call paintComponent() or paint() from the outside. Instead, let your image be created within those (overwritten) methods. Then you can be sure that your image will actually contain the painted content of the component.

Here is an example application. The ImagePanel will actually grab the graphics contents of the component every time it is painted, which might be a bit wasteful, so you may want to adjust the frequency with which this is done.

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

Like Martijn said, your image was probably black because the component wasn't even painted/displayed yet. You could add a ComponentListener to be notified when it is displayed. Your "solution" with getSubimage has nothing to do with the actual problem. I recommend you remove it.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!