Foro sobre Java SE > Guardar Imagen creada en Graphics de un JPanel
Es complicado entender exactamente qué es lo que pretendes hacer a partir de tu pregunta, pero que me queda claro es que no estás dibujando de modo correcto en Swing. Antes de hacer esa práctica necesitas aprender a dibujar. En este tutorial tienes una sección dedicada a eso:
http://www.javahispano.org/portada/2011/7/5/java-basico-con-ejemplos.html
@shao
En ocasiones anteriores, cuando has publicado el código que usas, se te ha podido ayudar.
Sigo sin entender esas reticencias con el código, tan habituales en este foro.
No es solo tu caso, es que parece una epidemia.
Disculpar si no lo subo...pero es que lo tengo todo disperso en métodos...no tengo ningún problema...lo subo...o si me decís algún sitio para dejar el código colgado lo dejo sin problemas...
Pego los trozos que yo pienso interesantes de código:
public class Principal extends javax.swing.JFrame {
private boolean opciones[];
private int iniX=0, iniY=0, actX=0, actY=0, finX=0, finY=0;
private int ancho=0, alto=0;
private Color color;
private BasicStroke relleno;
Graphics g;
BufferedImage image;
/**
* Creates new form Principal
*/
public Principal() {
initComponents();
this.opciones= new boolean[6];
this.g= this.jPanelAreaDibujo.getGraphics();
}
public void dibuja(){
this.jPanelAreaDibujo.paint(this.g);
}
public void dibujaRecta(Graphics g){
if(this.opciones[0]==true){
g.drawLine(this.iniX, this.iniY, this.finX, this.finY);
}else if(this.opciones[4]==true){
g.drawLine(this.iniX, this.iniY, this.actX, this.actY);
}
System.out.println("he pintado");
}
public void dibujaRectangulo(Graphics g){
calcularAncho();
calcularAlto();
if(this.iniX>this.finX)
if(this.iniY>this.finY)
//g.drawRect(this.finX, this.finY, this.ancho, this.alto);
g.fillRect(this.finX, this.finY, this.ancho, this.alto); // rectángulo rellenado
else
g.drawRect(this.finX, this.iniY, this.ancho, this.alto);
else if(this.iniY>this.finY)
g.drawRect(this.iniX, this.finY, this.ancho, this.alto);
else
g.drawRect(this.iniX, this.iniY, this.ancho, this.alto);
}
public void dibujaElipse(Graphics g){
calcularAncho();
calcularAlto();
if(this.iniX>this.finX)
if(this.iniY>this.finY)
g.drawOval(this.finX, this.finY, this.ancho, this.alto);
else
g.drawOval(this.finX, this.iniY, this.ancho, this.alto);
else if(this.iniY>this.finY)
g.drawOval(this.iniX, this.finY, this.ancho, this.alto);
else
g.drawOval(this.iniX, this.iniY, this.ancho, this.alto);
}
public void dibujaTexto(Graphics g){
if(this.jTextFieldTexto.getText().length()>0){
g.setFont( new Font( "Serif", Font.BOLD, 20 ) );
g.drawString(this.jTextFieldTexto.getText(), this.iniX, this.iniY);
}
}
private void jPanelAreaDibujoMousePressed(java.awt.event.MouseEvent evt) {
// TODO add your handling code here:
if(this.algunaOpcionSeleccionada()){
this.iniX=evt.getX();
this.actX=evt.getX();
this.iniY=evt.getY();
this.actY=evt.getY();
System.out.println("presiono");
}
}
private void jPanelAreaDibujoMouseReleased(java.awt.event.MouseEvent evt) {
// TODO add your handling code here:
if(this.algunaOpcionSeleccionada()){
this.finX=evt.getX();
this.actX=evt.getX();
this.finY=evt.getY();
this.actY=evt.getY();
System.out.println("suelto");
dibuja();
}
jPanelAreaDibujo = new javax.swing.JPanel(){
@Override
public void paint(Graphics g){
if(relleno!=null)
((Graphics2D)g).setStroke(relleno);
if(!algunaOpcionSeleccionada())
super.paint(g); //si lo comento guarda los elementos pintados. Sino borra y pinta el último elemento solo.
g.setColor(color);
int opcion= dibujaFigura();
switch(opcion){
case 0:
dibujaRecta(g);
break;
case 1:
dibujaRectangulo(g);
break;
case 2:
//dibujaCirculo(g);
break;
case 3:
dibujaElipse(g);
break;
case 4:
dibujaRecta(g);
break;
case 5:
dibujaTexto(g);
break;
}
}
};
Y he leído que para guardarlo en una imagen hay que hacer algo parecido a esto:
public Principal() {
initComponents();
this.opciones= new boolean[6];
this.image = new BufferedImage(this.jPanelAreaDibujo.getWidth(), this.jPanelAreaDibujo.getHeight(), BufferedImage.TYPE_INT_RGB);
// Hacemos el dibujo
this.g = image.createGraphics();
}
private void jMenuItemGuardarActionPerformed(java.awt.event.ActionEvent evt) {
File file = new File("C:\\Users\\Néstor\\Desktop\\imagen.jpg");
try {
ImageIO.write(image, "jpg", file); // Salvar la imagen en el fichero
} catch (IOException ex) {
System.out.println("Error al guardar archivo.");
}
}
Sin añadir el código que pongo primero...me dibuja todo perfectamente sobre el JPanel. Si añado el código que pongo después para poder guardar en un fichero...sobre la interfaz no me dibiuja nada pero cuando lo guardo esta todo lo que he dibujado guardado...
Ayuda!!!
Gracias de antemano.
Saludos.
Este es un sitio muy conocido y usado:
http://pastebin.com/
Un par de comentarios, tras ver el código.
1.- El método paint se puede sobreescribir, pero no está pensado para llamarlo directamente. JPanel tiene el método repaint() que se llama cuando es necesario redibujar.
http://docs.oracle.com/javase/7/docs/api/javax/swing/JComponent.html#paint(java.awt.Graphics)
"Applications should not invoke paint directly, but should instead use the repaint method to schedule the component for redrawing."
2.- El JPanel tiene métodos para crear una imagen.
http://docs.oracle.com/javase/7/docs/api/java/awt/Component.html#createImage(java.awt.image.ImageProducer)
choces esa página es para subir código???
Es cierto que no se debe sobreescribir el paint() pero era para hacer una práctica.
Después de usar hacer esta prueba sencilla en el código del constructor del JFrame:
this.image=(BufferedImage)this.jPanelAreaDibujo.createImage(this.jPanelAreaDibujo.getWidth(), this.jPanelAreaDibujo.getHeight());
this.g= this.image.getGraphics();
this.g.drawRect(0, 0, 20, 20);
y despues de implementar un método en el que guardo lo dibujado:
File file = new File("C:\\Users\\Néstor\\Desktop\\imagen.jpg");
try {
ImageIO.write(image, "jpg", file); // Salvar la imagen en el fichero
} catch (IOException ex) {
System.out.println("Error al guardar archivo.");
}
sigue sin funcionar...si pongo lo de BufferedImage me guarda lo que hago, pero no me lo muestra en el JPanel.....que puede estar pasando???voy loco ya con este tema
Sí, para eso sirve esa página.
Guardar y Pintar son dos procesos que deben estar bien separados.
Con este método public void paintComponent(final Graphics graphics) de JComponent se realizan todas las operaciones de dibujado. Hay que poner mucha atención a los comentarios de su Javadoc.
http://docs.oracle.com/javase/7/docs/api/javax/swing/JComponent.html#paintComponent(java.awt.Graphics)
Si quieres guardar una imagen, basta con crearla, con el método createImage, y guardar el Image sin más. El código que lo realice debería estar en un método.
A estas líneas que incluyes en tu constructor, no les veo sentido:
this.g= this.image.getGraphics();
this.g.drawRect(0, 0, 20, 20);
Ya he subido el código:
http://pastebin.com/Wmi8QCnZ
this.g= this.image.getGraphics();
this.g.drawRect(0, 0, 20, 20);
La primera la hago porque tengo una variable en mi clase de tipo Graphics y dibujo sobre ese graphics. Y la segunda era una prueba para ver si realmente dibujaba algo o no...
Sigue sin funcionarme. He puesto el código de:
this.image=(BufferedImage)this.jPanelAreaDibujo.createImage(this.jPanelAreaDibujo.getWidth(), this.jPanelAreaDibujo.getHeight());
File file = new File("C:\\Users\\Néstor\\Desktop\\imagen.jpg");
try {
ImageIO.write(image, "jpg", file); // Salvar la imagen en el fichero
} catch (IOException ex) {
System.out.println("Error al guardar archivo.");
}
dentro de un método como lo tenia, que solo llamo cuando le doy al menu guardar, y no me guarda nada...asi veo lo que dibujo pero no me lo guarda. Antes no veia lo que dibujaba pero lo guardaba....por favor mirad si podéis el código y me comentais, estoy desesperado ya.
Gracias.
Saludos.
Me he debido de explicar muy mal.
Esas dos líneas sobran. Por eso decía que no les veía sentido.
El campo Graphics g; no es necesario.
El método que necesitas usar para redibujar es repaint()
public void dibuja() {
this.jPanelAreaDibujo.repaint();
}
Y el que tienes que sobreescribir es paintComponent
jPanelAreaDibujo = new javax.swing.JPanel() {
@Override
public void paintComponent(Graphics g)
Hola choces...
pero haciéndolo como tu dices...no me dibuja ni la interfaz...según voy pasando el ratón me va dibujando los botones etc etc...y cuando dibujo algo sobre el JPanel sale pero todo muy desestructurado. A la hora de guardar..sigue igual...no guarda nada.
Mi código está subido. No es extenso...si alguien le puede echar un vistazo y ayudarme por favor. Necesito solucionarlo.
Gracias.
Haciendo esos cambios, lo que obtienes es un StackOverflow, debido a:
if(!algunaOpcionSeleccionada())
super.paint(g);
Porque estás llamando al método paint, que es de AWT desde un método sobreescrito de Swing.
Es esto lo que deberías usar:
if (!algunaOpcionSeleccionada()) {
super.paintComponent(g);
}
Como digo es como debe hacerse, según las especificaciones de Swing. Otra cuestión es que aparezcan problemas que haya que resolver.
Con este código puedes guardar lo dibujado:
this.image = new BufferedImage(jPanelAreaDibujo.getWidth(), this.jPanelAreaDibujo.getHeight(), BufferedImage.TYPE_INT_ARGB);
final Graphics graphics = image.getGraphics();
jPanelAreaDibujo.paint(graphics);
graphics.dispose();
File file = new File("imagen.png");
try {
ImageIO.write(image, "png", file); // Salvar la imagen en el fichero
} catch (IOException ex) {
System.out.println("Error al guardar archivo.");
}
Pues nada...no me va...si pinta en la pantalla no guarda...y si no pinta en la pantalla lo guarda...
El problema es que cuando creo el objeto BufferedImage, eso tiene un objeto graphics asociado, el el cual se pinta. No hay ningún método que le puedas asignar otro graphics. Entonces cuando usas ese graphics en tu método paint o paintComponent o paintComponents dibuja sobre el y lo guarda, pero no lo ves visualmente. En cambio si lo ves visualmente estas dibujando sobre el graphics del jpanel, pero a la hora de crear el objeto BufferedImage y guardarlo, se crea uno nuevo vacio.
¿Alguna solución?
Ayuda por favor, necesito solucionar esto.
Gracias.
Con los cambios que te he propuesto, me funciona bien: dibuja y guarda.
Hola a todos,
he hecho un paint básico (quiero ampliarlo más adelante) que dibujo rectas, rectángulos, etc etc. Lo pinto en el Graphics de un JPanel...pero a la hora de guardarlo he intentado esto pero no me funciona:
BufferedImage image = new BufferedImage(200, 200, BufferedImage.TYPE_INT_RGB);
Graphics2D g = image.createGraphics();
Y luego llamo al método paint(g) del panel pasándole ese objecto Graphics creado. Pero cuando dibujo sobre el panel no me dibuja nada..pero cuando lo guardo...está todo guardado (aunque todo con fondo negro y lo pintado en blanco..).
¿Alguien me dice cómo puedo hacer que me lo dibuje en el panel y además lo pueda guardar en el fichero?
Saludos.