5

我有一个快速的问题。如何获取由 JComponent.paint 或 paintComponent 生成的图像?

我有一个 JComponent,我将其用作“工作区”,并在其中将 paintComponent 方法覆盖为我自己的。问题是我的工作区 JComponent 也有孩子,他们有自己的 paintComponent 方法。

所以当 Swing 渲染我的工作区组件时,它会渲染工作区图形,然后是它的子组件。

但是,我想获取我的工作区组件生成的图像(包括工作区图形和子图形)。

我怎么做?

我尝试使用自己的图形自己调用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;
}

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

4

4 回答 4

3

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

于 2008-09-22T09:04:38.203 回答
1

似乎问题是由于 BufferedImage 是如何创建的。使用时:

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

相反,它奏效了。我还必须将 switch 从paintComponent 更改为paint 以渲染孩子。

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

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

总是渲染黑色图像?离题,但可能会很有趣:)

于 2008-09-22T09:46:34.730 回答
0

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

于 2008-09-22T14:04:12.867 回答
0

将新的 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;
}
于 2010-09-02T14:06:59.613 回答