2008-09-22 10 views
5

Tôi có câu hỏi nhanh. Làm cách nào để tôi nhận được hình ảnh được tạo bởi JComponent.paint hoặc paintComponent?Làm cách nào để có được hình ảnh sơn/paintComponent tạo ra?

Tôi có một JComponent mà tôi sử dụng làm 'không gian làm việc' và nơi tôi đã ghi đè phương pháp paintComponent cho chính mình. Vấn đề là JComponent không gian làm việc của tôi cũng có trẻ em có các phương thức paintComponent riêng của chúng.

Vì vậy, khi Swing hiển thị thành phần không gian làm việc của tôi, nó sẽ hiển thị đồ họa không gian làm việc và sau đó là childrens '.

Tuy nhiên, tôi muốn lấy hình ảnh thành phần không gian làm việc của tôi tạo (bao gồm đồ họa không gian làm việc và đồ họa của trẻ em).

Tôi làm như thế nào?

Tôi đã cố gọi chính phương thức paintComponent/paint bằng cách sử dụng đồ họa của riêng mình, nhưng tôi vừa trả về một hình ảnh đen. Đây là những gì tôi đã thử;

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

Bất kỳ suy nghĩ hoặc nhận xét nào đều được hoan nghênh! :)

Trả lời

3

Nếu bạn gọi getImage quá sớm, thành phần của bạn sẽ không được hiển thị và vẫn sẽ có chiều rộng và chiều cao 0. Bạn đã chắc chắn rằng bạn đang gọi nó vào một thời gian đủ muộn? Hãy thử in kích thước của thành phần để stdout và xem kích thước của nó là gì.

+0

Phương thức 'getImage' được gọi bởi người dùng, nghĩa là ứng dụng có nhiều thời gian. – user20298

1

Dường như vấn đề là do cách tạo BufferedImage. Khi sử dụng:

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

Thay vào đó nó hoạt động. Tôi cũng đã phải thay đổi chuyển đổi từ paintComponent để vẽ để làm cho trẻ em.

Sự cố được giải quyết, nhưng nếu có ai biết. Tại sao tôi:

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

Luôn hiển thị hình ảnh đen? Offtopic, nhưng có thể thú vị để biết :)

+0

Tôi đã có một vấn đề tương tự - thay đổi kiểu BufferedImage mới thành BufferedImage.TYPE_INT_RGB đã giải quyết được sự cố. –

0

Không gọi paintComponent() hoặc paint() từ bên ngoài. Thay vào đó, hãy để hình ảnh của bạn được tạo trong các phương thức (ghi đè). Sau đó, bạn có thể chắc chắn rằng hình ảnh của bạn thực sự sẽ chứa nội dung được vẽ của thành phần.

Đây là một ứng dụng mẫu. ImagePanel sẽ thực sự lấy nội dung đồ họa của thành phần mỗi khi nó được sơn, có thể là một chút lãng phí, vì vậy bạn có thể muốn điều chỉnh tần số mà điều này được thực hiện.

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

Như Martijn đã nói, hình ảnh của bạn có thể là màu đen vì thành phần này vẫn chưa được sơn/hiển thị. Bạn có thể thêm một ComponentListener để được thông báo khi nó được hiển thị. "Giải pháp" của bạn với getSubimage không liên quan gì đến vấn đề thực tế. Tôi khuyên bạn nên loại bỏ nó.

+0

_Không gọi sơn() từ bên ngoài_ chỉ đơn giản là sai .. bạn chắc chắn có thể gọi sơn từ bất cứ nơi nào bạn muốn - đó là một phương pháp công cộng mà không có bất kỳ hạn chế. – kleopatra

0

Thay đổi BufferedImage mới thành TYPE_INT_RGB giải quyết vấn đề này cho tôi. Tôi không thể đưa ra một lời giải thích mặc dù - chỉ là một bí ẩn Swing.

public BufferedImage getImage() { 

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

    return hello; 
}