java - que - ¿Cómo obtengo la imagen paint/paintComponent genera?
label java swing (4)
Parece que el problema se debió a cómo se creó BufferedImage. Cuando usas:
BufferedImage hello = bufferedImage.getSubimage(0,0, getWidth(), getHeight());
En cambio, funcionó. También tuve que cambiar el interruptor de paintComponent por pintar para representar a los niños.
Problema resuelto, pero si alguien sabe. ¿Por qué mi:
BufferedImage hello = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB);
¿Siempre renderizas una imagen negra? Offtopic, pero podría ser interesante saber :)
Tengo una pregunta rápida. ¿Cómo obtengo la imagen generada por JComponent.paint o paintComponent?
Tengo un JComponent que uso como un ''espacio de trabajo'' y donde he sobrescrito el método paintComponent al mío. El hecho es que mi espacio de trabajo JComponent también tiene hijos, que tiene sus propios métodos paintComponent.
Entonces, cuando Swing representa mi componente de espacio de trabajo, representa los gráficos del espacio de trabajo y luego los de sus hijos.
Sin embargo, quiero obtener la imagen que genera mi componente de espacio de trabajo (que incluye los gráficos del espacio de trabajo y los gráficos para niños).
¿Cómo puedo hacer eso?
Traté de llamar al método paintComponent / paint usando mis propios gráficos, pero acabo de devolver una imagen en negro. Esto es lo que intenté;
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;
}
¡Cualquier pensamiento o comentario es bienvenido! :)
Si llama a getImage demasiado pronto, su componente no se habrá mostrado aún y aún tendrá un ancho y alto de 0. ¿Te has asegurado de llamarlo con suficiente retraso? Intente imprimir el tamaño del componente a stdout y vea cuáles son sus dimensiones.
Cambiar la nueva imagen Buffered a TYPE_INT_RGB resuelve esto para mí. Aunque no puedo dar una explicación, solo un misterio de Swing.
public BufferedImage getImage() {
BufferedImage hello = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_RGB);
Graphics g = hello.getGraphics();
paintComponent( g );
return hello;
}
No llame a paintComponent () o paint () desde el exterior. En cambio, permita que su imagen se cree dentro de esos métodos (sobrescritos). Entonces puede estar seguro de que su imagen contendrá el contenido pintado del componente.
Aquí hay una aplicación de ejemplo. El ImagePanel captará los contenidos gráficos del componente cada vez que se lo pinte, lo que puede ser un poco inútil, por lo que es posible que desee ajustar la frecuencia con la que se realiza.
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);
}
});
}
}
Como dijo Martijn, tu imagen probablemente era negra porque el componente ni siquiera estaba pintado / mostrado aún. Puede agregar un ComponentListener para recibir una notificación cuando se muestre. Su "solución" con getSubimage no tiene nada que ver con el problema real. Te recomiendo que lo elimines