Foros del Web » Programación para mayores de 30 ;) » Java »

Dibujo con canvas

Estas en el tema de Dibujo con canvas en el foro de Java en Foros del Web. Hola, espero que esten bien. Estoy haciendo un programa en java, que basicamente, lo que hace es que cada vez que hago click en la ...
  #1 (permalink)  
Antiguo 15/06/2010, 14:47
 
Fecha de Ingreso: mayo-2010
Mensajes: 10
Antigüedad: 14 años, 6 meses
Puntos: 1
Dibujo con canvas

Hola, espero que esten bien.

Estoy haciendo un programa en java, que basicamente, lo que hace es que cada vez que hago click en la ventana, se crea un nodo.

Luego, si haglo click sobre ese nodo y muevo el mouse, el nodo se deberia mover en tiempo real junto con el mouse a donde uno escoja.

Estoy usando canvas y ya sobreesrubí el metodo paint(graphics g) y lo que puse ahi fue que me dibujara todos los nodos que tenia creados.

Todo funciona bien, los nodos aparecen y se mueven, pero tengo un problema con el refrescamiento. A veces, cuando muevo un nodo, la pantalla no refresca bien, y se ve como si los nodos desparacen y aparecen rapidamente.

Entre mas nodos inserto, mas aumenta el problema de refrescamiento, desaparecen y aparecen con mas frecuencia.

Saben como solucionar esto? Basicamente mi problema es ese, el refrescamiento del canvas. yo uso el metodo repaint cada vez que necesito refrescar el canvas.
  #2 (permalink)  
Antiguo 15/06/2010, 15:29
Avatar de chuidiang
Colaborador
 
Fecha de Ingreso: octubre-2004
Mensajes: 3.774
Antigüedad: 20 años, 1 mes
Puntos: 454
Respuesta: Dibujo con canvas

Lo del método repaint() no queda más remedio. Lo que puedes hacer es dibujar aparte, me explico.

En el método paint() crea un BufferedImage del mismo tamaño que el Canvas (pide getWidth() y getHeight() al Canvas para determinar ese tamaño). Dibuja sobre el BufferedImage, pidiéndole el getGraphics() y usando eso para pintar. Una vez que tengas todos los nodos dibujados en el BufferedImage, pinta ese BufferedImage completo sobre el Canvas. No hagas un borrado previo del Canvas, ya que eso aumenta el parpadeo.

En resumen, el código se parecería a esto

Código java:
Ver original
  1. public void paint (Graphics g) {
  2.    BufferedImage imagen = new BufferedImage (getWidht(), getHeight(), ...);
  3.    imagen.getGraphics().draw....
  4.    ....
  5.    g.drawImage(imagen, 0, 0, ....);
  6. }

Aquí tienes algo más detallado http://chuwiki.chuidiang.org/index.p...l_doble_buffer

Se bueno.
__________________
Apuntes Java
Wiki de Programación
  #3 (permalink)  
Antiguo 15/06/2010, 16:37
 
Fecha de Ingreso: mayo-2010
Mensajes: 10
Antigüedad: 14 años, 6 meses
Puntos: 1
Respuesta: Dibujo con canvas

Hola, gracias por responderme, ya escribi el codigo y quedo de la manera como me dijiste, con el double buffer.

Pero algo hice mal porke no me pinta los nodos. Solo deja blanco el fondo de la pantalla.

aqui está el codigo del paint(graphics g)

Código:
public void paint(Graphics g){
        BufferedImage imagen = new BufferedImage (this.WIDTH, this.HEIGHT, BufferedImage.TYPE_4BYTE_ABGR);

      // Se dibuja en la imagen
         for(Nodo n:grafo.nodos){
             imagen.getGraphics().drawOval(n.posX(), n.posY(), n.ancho(), n.alto());
           for(Nodo n2:n.sucesores)
              imagen.getGraphics().drawLine(n.posX(), n.posY(), n2.posX(), n2.posY());
        }

      // Se "pega" la imagen sobre el componente
        g.drawImage(imagen, 0, 0, this);

    }
Tengo el error en esta parte?
  #4 (permalink)  
Antiguo 15/06/2010, 21:10
Avatar de chuidiang
Colaborador
 
Fecha de Ingreso: octubre-2004
Mensajes: 3.774
Antigüedad: 20 años, 1 mes
Puntos: 454
Respuesta: Dibujo con canvas

Hola:

Después de crear el BufferedImage y antes de ponerte a dibujar en él, rellénalo con un rectángulo del tamaño del BufferedImage y del color de fondo que quieras.

Se bueno.
__________________
Apuntes Java
Wiki de Programación
  #5 (permalink)  
Antiguo 15/06/2010, 21:51
 
Fecha de Ingreso: mayo-2010
Mensajes: 10
Antigüedad: 14 años, 6 meses
Puntos: 1
Respuesta: Dibujo con canvas

Hice esto:

Hice lo del rectángulo, pero no se si lo que hice, era lo que te referias.

Lo que pasa es que, se abre la ventana, con el canvas mostrando el fondo blanco. Pero no dibuja nada, si quito lo del bufferedImage, entonces si lo dibuja.

Perdon por ser tan insistente, pero es que realmente quiero aprender a dibujar en el canvas, objetos y que se vean bien. De hecho, quisiera mas adelante agregar imagenes en cada nodo, en vez de que sean solo una linea circular, pero para eso ya masomenos tengo idea de como hacerlo. Lo que pasa es que el refrescamiento, es el que me está molestando en estos momentos.

Y gracias por la ayuda que me has dado.

Aqui dejo el codigo que tengo solo para el panel, si necesitas mas codigo de otras clases nada mas me dices.

Código:
  Grafo grafo;

    public PanelNodos(){

        grafo=new Grafo();

        setBackground(Color.white);

        addMouseListener(new MouseListener(){
            public void mouseClicked(MouseEvent e){
                crearNodo(e);
            }

            public void mousePressed(MouseEvent e) {
                seleccionarNodo(e);
            }

            public void mouseReleased(MouseEvent e) {
                soltarNodo(e);
            }

            public void mouseEntered(MouseEvent e) {
//                throw new UnsupportedOperationException("Not supported yet.");
            }

            public void mouseExited(MouseEvent e) {
  //              throw new UnsupportedOperationException("Not supported yet.");
            }
        });

          addMouseMotionListener(new MouseMotionListener(){

            public void mouseDragged(MouseEvent e) {
                moverNodo(e);
            }

            public void mouseMoved(MouseEvent e) {
    //            throw new UnsupportedOperationException("Not supported yet.");
            }
    });

    }

    public void crearNodo(final MouseEvent e){
        
        grafo.agregarNodo(e.getX(), e.getY(), 20, 20);
        repaint();
     /*   new Runnable() {

            public void run() {
               grafo.agregarNodo(e.getX(), e.getY(), 20, 20);
            }
        };*/
    }

    public void seleccionarNodo(final MouseEvent e){
        grafo.seleccionarNodo(e.getX(), e.getY());
      /*  new Runnable(){

            public void run() {
                grafo.seleccionarNodo(e.getX(), e.getY());
            }

        };*/
    }

    public void soltarNodo(MouseEvent e){
          if(e.getButton()==e.BUTTON1)
              grafo.soltarNodo();
          else
          if(e.getButton()==e.BUTTON3){
              grafo.agregarSucesor();
              repaint();
          }
          /*
        new Runnable(){

            public void run() {
                grafo.soltarNodo();
            }

        };*/
    }

    public void moverNodo(final MouseEvent e){
        
        grafo.moverNodo(e.getX(), e.getY());
        repaint();

    }

    public void dibujarNodos(BufferedImage imagen){
        for(Nodo n:grafo.nodos){
            imagen.getGraphics().drawOval(n.posX(), n.posY(), n.ancho(), n.alto());
        }
    }

    public void dibujarArcos(BufferedImage imagen){
        for(Nodo n:grafo.nodos){
           for(Nodo n2:n.sucesores)
               imagen.getGraphics().drawLine(n.posX(), n.posY(), n2.posX(), n2.posY());
        }
    }

    public void paint(Graphics g){
        BufferedImage imagen = new BufferedImage (this.WIDTH, this.HEIGHT, BufferedImage.TYPE_INT_RGB);
        imagen.getGraphics().setColor(Color.red);
        imagen.getGraphics().fillRect(0, 0, 800, 600);


      // Se dibuja en la imagen
         for(Nodo n:grafo.nodos){
             imagen.getGraphics().drawOval(n.posX(), n.posY(), n.ancho(), n.alto());
          /* for(Nodo n2:n.sucesores)
              imagen.getGraphics().drawLine(n.posX(), n.posY(), n2.posX(), n2.posY());
        */}



      // Se "pega" la imagen sobre el componente
        g.drawImage(imagen, 0, 0, this);

    }
  #6 (permalink)  
Antiguo 16/06/2010, 06:00
Avatar de chuidiang
Colaborador
 
Fecha de Ingreso: octubre-2004
Mensajes: 3.774
Antigüedad: 20 años, 1 mes
Puntos: 454
Respuesta: Dibujo con canvas

Hola:

A mi el siguiente trozo de código me funciona correctamente, me sale un ovalo blanco sobre fondo negro
Código java:
Ver original
  1. import java.awt.Canvas;
  2. import java.awt.Graphics;
  3. import java.awt.image.BufferedImage;
  4.  
  5. import javax.swing.JFrame;
  6.  
  7. public class PruebaCanvas
  8. {
  9.  
  10.     /**
  11.      * @param args
  12.      */
  13.     public static void main( String [] args)
  14.     {
  15.         JFrame f = new JFrame();
  16.         Canvas c = new Lienzo();
  17.         f.getContentPane().add(c);
  18.         f.setSize(200, 200);
  19.         f.setVisible(true);
  20.     }
  21.  
  22. }
  23.  
  24. class Lienzo extends Canvas {
  25.     public void paint(Graphics g){
  26.         BufferedImage imagen = new BufferedImage(200, 200, BufferedImage.TYPE_INT_BGR);
  27.         imagen.getGraphics().drawOval(50, 50, 20, 30);
  28.         g.drawImage(imagen,0,0,this);
  29.     }
  30. }

Se bueno.
__________________
Apuntes Java
Wiki de Programación
  #7 (permalink)  
Antiguo 04/12/2010, 22:41
 
Fecha de Ingreso: diciembre-2010
Mensajes: 1
Antigüedad: 13 años, 11 meses
Puntos: 1
Respuesta: Dibujo con canvas

Yo tuve ese mismo problema, lo que sucede es lo siguiente, cuando tu llamas al metodo repaint(); estas diciendo que te borre todo el lienzo y vuelva a dibujar cada uno de sus elementos.. , y por lo que necesitas no es necesario, para solucionarlo creas la siguiente variable:
Graphics nuevoG;
y en tu constructos añades ko siguiente:

setBackground(Color.white); // con eso tenemos fondo blanco

y cuando quieras dibujar usas:

nuevoG = getGraphics();
gc.setXORMode(getBackground()); //este codigo entre otras cosas lo usaremos para borrar solo un segmento del lienzo

es decir, si tu dibujas un punto negro
gc.drawfill(100,100,10,10); -> ejecutas
ahora copia dos veces la misma linea
que te quede asi...
gc.drawfill(100,100,10,10);
gc.drawfill(100,100,10,10); - ejecutas denuevo
vez q desaparece??
has el siguiente cambio
gc.drawfill(100,100,10,10);
gc.drawfill(105,105,10,10);


ES DECIR POR CADA ITERACCIÓN TIENES QUE HACER LOS SIGUIENTE
-DIBUJAR POSICIÓN ANTERIOR (PARA BORRAR)
-DIBUJAR POSICIÓN ACTUAL (PARA PINTAR)

CON ESTO HACEMOS AHORRO DE MEMORIA... porque no borramos todo el contenido del lienzo y la situación se vuelve mas amena... si quiers más info a mi mail.. oks.

[email protected]
  #8 (permalink)  
Antiguo 13/02/2012, 20:18
Avatar de loganbdn  
Fecha de Ingreso: enero-2009
Ubicación: Badalona
Mensajes: 114
Antigüedad: 15 años, 10 meses
Puntos: 1
Respuesta: Dibujo con canvas

Tengo un problema en el que uso Canvas y lo que quiero hacer es que en un lienzo cuando dibujo no se me borre lo que he dibujado.
El codigo para dibujar una imagen lo tengo metido en un Paint(Graphics g) pero a cada iteracion me borra el fondo dibujado y me coloca el siguiente dibujo en la posicion movida de unas coordenadas que le doy.
Yo quiero que no me borre lo anterior pero lo veo imposible porque Paint() siempre me lo borra.
  #9 (permalink)  
Antiguo 02/10/2012, 04:43
 
Fecha de Ingreso: octubre-2012
Mensajes: 1
Antigüedad: 12 años, 1 mes
Puntos: 0
Respuesta: Dibujo con canvas

Los ejemplos que es posible hallar en internet para dibujar en un lienzo, suelen tener tantos elementos y métodos, que resulta muy difícil entenderlos, y por ello nada didácticos. Un código muy básico para poder hacer líneas en un lienzo, el cual puede ser completado para mejorar el programa, es:


import java.awt.*;
import java.awt.event.*;


public class Ventana extends Frame implements ActionListener {

int long_x=700, long_y=500;
Lienzo l;

public static void main(String[] args) {
new Ventana();
}


public Ventana(){
// Esta parte define la funcionalidad básica de la ventana.
super("Lienzo");
setLocationRelativeTo(null);
setLayout(null);
setSize(long_x, long_y);

addWindowListener(
new WindowAdapter(){
public void windowClosing(WindowEvent e){System.exit(0);}
}
);

add(l=new Lienzo(long_x, long_y));
l.setBounds(150, 0, long_x-150, long_y);

setVisible(true);
}
}




import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;


public class Lienzo extends Canvas implements MouseListener, MouseMotionListener{

int x, y, x2, y2;
BufferedImage imagen;
Graphics2D g0;

public Lienzo(int ancho, int alto){
setBackground(Color.white);
addMouseMotionListener(this);
addMouseListener(this);

imagen = new BufferedImage(ancho, alto, BufferedImage.TYPE_INT_RGB);
g0 = imagen.createGraphics();
g0.setColor(Color.white);
g0.fillRect(0, 0, ancho, alto);
g0.setStroke(new BasicStroke(3));
g0.setColor(Color.black);
}


public void paint(Graphics g){
g.drawImage(imagen, 0, 0, null);
}


public void mouseDragged(MouseEvent e) {
x2 = e.getX();
y2 = e.getY();
g0.drawLine(x, y, x2, y2);
paint(getGraphics());
x = x2;
y = y2;
}


public void mouseMoved(MouseEvent e){ }


public void mouseEntered(MouseEvent e){ }


public void mouseExited(MouseEvent e){ }


public void mouseClicked(MouseEvent e){ }


public void mousePressed(MouseEvent e){
x = e.getX();
y = e.getY();
}


public void mouseReleased(MouseEvent e){ }
}



No es posible utilizar el objeto de Graphics 'g0' del objeto de BufferedImage 'imagen', porque el método "paint(Graphics g)" solamente permite dibujar en el panel, con un elemento de Graphics obtenido del mismo lienzo. Así que no es posible escribir directamente "paint(g0)" en lugar de "paint(getGraphics())" en el método "public void mouseDragged(MouseEvent e)"; sino que dentro del método "paint(Graphics g)", hay que escribir en 'g' lo dibujado en 'g0'. Además, no vale guardar el una variable el objeto obtenido con "getGraphics()". Parece ser que tras cada uso es eliminado automáticamente, por lo que después será lanzada la excepción: NullPointerException.
Haciendo esto así, es posible recuperar el dibujo después de minimizar la ventana, pues queda guardado en 'imagen', y al restaurar la ventana, será llamado automáticamente el método "paint(Graphics g)", que redibujará ese contenido. Además, así es posible guardar la imagen hecha, importando "javax.imageio.ImageIO", y escribiendo: ImageIO.write(imagen, "png", new File("Dibujo.png")); o lo mismo cambiando la extensión del archivo, y el archivo y su dirección, ¡claro!


Me resultó difícil hallar el medio de combinar el dibujado dinámico de un programa del estilo del Paint de Windows, con el poder restaurar la imagen tras haber minimizado la ventana, y poder guardar el resultado; pero esto lo soluciona todo. ¡Suerte con las mejoras!


Autor: OSLF.

Etiquetas: canvas, dibujo
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta

SíEste tema le ha gustado a 1 personas




La zona horaria es GMT -6. Ahora son las 10:53.