如何获取 Paint/paintComponent 生成的图像?

发布于 2024-07-05 00:06:39 字数 922 浏览 7 评论 0原文

我有一个快速的问题。 如何获取 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;
}

欢迎任何想法或评论! :)

I have a quick question. How do I get the image generated by a JComponent.paint or paintComponent?

I have a JComponent which I use as a 'workspace' and where I have overwritten the paintComponent method to my own. The thing is that my workspace JComponent also has children which has their own paintComponent methods.

So when Swing renders my workspace component, it renders the workspace graphics and then its childrens'.

However, I want to get the image my workspace component generates (which includes the workspace graphics and the children's graphics).

How do I do that?

I tried to call the paintComponent/paint-method myself by using my own Graphics, but i just returned a black image. Here is what i tried;

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

Any thoughts or comments are welcome! :)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

那些过往 2024-07-12 00:06:40

将新的 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;
}

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;
}
ま柒月 2024-07-12 00:06:40

不要从外部调用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 的“解决方案”与实际问题无关。 我建议你删除它。

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.

清旖 2024-07-12 00:06:40

似乎问题是由于 BufferedImage 的创建方式造成的。 使用时:

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

相反它有效。 我还必须将 switch 从 PaintComponent 更改为 Paint 来渲染子项。

问题解决了,但如果有人知道的话。 为什么我的:

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

总是呈现黑色图像? 题外话,但了解一下可能会很有趣:)

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 :)

单身狗的梦 2024-07-12 00:06:40

如果您太早调用 getImage,您的组件将尚未显示,并且宽度和高度仍为 0。 您是否确定在足够晚的时间调用它? 尝试将组件的大小打印到标准输出并查看其尺寸。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文