2008-09-22 2 views
5

У меня есть быстрый вопрос. Как получить изображение, созданное компонентом JComponent.paint или paintComponent?Как получить изображение 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; 
} 

Любые мысли или комментарии приветствуются! :)

ответ

3

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

+0

Метод 'getImage' вызывается пользователем, то есть приложение имеет много времени. – user20298 2008-09-22 09:12:59

1

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

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

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

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

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

Всегда визуализируйте черное изображение? Offtopic, но может быть интересно знать :)

+0

У меня была аналогичная проблема - смена нового типа BufferedImage на BufferedImage.TYPE_INT_RGB решила проблему. – 2010-09-02 14:05:04

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 не имеет ничего общего с реальной проблемой. Я рекомендую удалить его.

+0

_Do не вызывать краску() извне_ просто неправильно .. вы, безусловно, можете вызвать краску из того, что хотите - это общедоступный метод без каких-либо ограничений. – kleopatra 2012-01-13 11:25:42

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; 
} 
Смежные вопросы