Как получить изображение, которое генерирует paint / paintComponent? - PullRequest
5 голосов
/ 22 сентября 2008

У меня быстрый вопрос. Как получить изображение, сгенерированное JComponent.paint или paintComponent?

У меня есть JComponent, который я использую в качестве «рабочего пространства» и где я переписал метод paintComponent своим собственным. Дело в том, что в моем рабочем пространстве JComponent также есть дочерние элементы, у которых есть свои собственные методы paintComponent.

Поэтому, когда Swing отображает мой компонент рабочей области, он отображает графику рабочей области, а затем ее дочерние элементы.

Однако я хочу получить изображение, которое генерирует мой компонент рабочего пространства (включая графику рабочего пространства и детскую графику).

Как мне это сделать?

Я пытался вызвать метод paintComponent / paint самостоятельно, используя мою собственную Графику, но я только что возвратил черное изображение. Вот что я попробовал;

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 ]

3 голосов
/ 22 сентября 2008

Если вы вызываете getImage слишком рано, ваш компонент еще не будет отображаться и будет по-прежнему иметь ширину и высоту 0. Вы убедились, что звоните достаточно поздно? Попробуйте напечатать размер компонента в стандартный вывод и посмотрите, каковы его размеры.

1 голос
/ 22 сентября 2008

Похоже, проблема была в том, как был создан BufferedImage. При использовании:

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

Вместо этого это сработало. Мне также пришлось изменить переключатель с paintComponent на рисование, чтобы отобразить дочерние элементы.

Проблема решена, но если кто знает. Почему мой:

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

Всегда рендерить черное изображение? Оффтоп, но может быть интересно узнать:)

0 голосов
/ 02 сентября 2010

Изменение нового 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;
}
0 голосов
/ 22 сентября 2008

Не вызывайте 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);
            }
        });
    }
}

Как сказал Мартин, ваше изображение, вероятно, было черным, потому что компонент еще даже не был нарисован / отображен. Вы можете добавить ComponentListener, чтобы получать уведомления при его отображении. Ваше «решение» с getSubimage не имеет ничего общего с реальной проблемой. Я рекомендую вам удалить его.

...