Sobre escribir método paint de un jpanel
Los foristas, tengo el siguiente inconveniente, deseo pintar en un Jpanel que se encuentra en un jframe, lo que se pintara en en jpanel se debe actualizar a cada momento mi duda es, ¿cómo le envío al jpanel el gráfico ya que me encuentro es en el jframe y este es el que iniciare? Si reescribo el método pint(), este sera el del jframe, pero como hago para que se pinte en el Jpanel lo que deseo.
1 respuesta
Respuesta de alejosoft
1
1
alejosoft, 3 años de experiencia como Ingeniero de Sistemas, I speak English...
Una forma de hacer esto es crear una clase que extienda a JPanel, de esa forma podrás no solamente reescribir el método paint, sino también declarar atributos públicos que podrán ser accesados desde tu JFrame... he creado un ejemplo sencillo usando dos clases:
1) MyJPanel: que es nuestro JPanel que reescribe al método paint y declara un atributo publico "public String texto" que puede ser usado desde cualquier otra clase. Aquí esta el código:
import javax.swing.*;
import java.awt.*;
// este es nuestro JPanel personalizado.
public class MyJPanel extends JPanel{
// este atributo es publico para que pueda ser
// usado desde la clase MyJFrame
public String texto;
// reescribimos el metodo paint
// este metodo es invocado cada vez que se requiera
// una actualizacion grafica de este JPanel
public void paint(Graphics g){
// primero dibujamos el fondo blanco
g.setColor(Color.white);
g.fillRect(0,0,this.getWidth(),this.getHeight());
// ahora dibujamos el String que se encuentra en la variable texto
g.setColor(Color.black);
if ( texto != null){
g.drawString(texto,10,20);
}
else {
// si la variable texto es nula, dibujamos entonces un mensaje
// amigable ;)
g.drawString("Hola, este es MyJpanel, cualquier cosa que escribas en el campo lo mostrare aqui",10,20);
}
}
}
2) MyJFrame: que es la ventana que nos permite ejecutar el ejemplo y ver nuestro JPanel funcionando. Aquí esta el código:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class MyJFrame extends JFrame {
// este es nuestro JPanel personalizado
private MyJPanel myJPanel;
public MyJFrame(){
// un campo de texto que usaremos para dibujar, lo que el usuario
// escriba en el, sobre nuestro JPanel.
JTextField campo = new JTextField("Escriba algo aqui");
// agregamos un oyente de evento de teclado
campo.addKeyListener(new KeyAdapter(){
// lo que se ponga en el cuerpo de este metodo
// se ejecutara cada vez que una tecla sea liberada
// sobre nuestro campo de texto.
public void keyReleased(KeyEvent e){
// pasamos el texto escrito en nuestro campo a la variable
// texto definida en nuestra clase MyJPanel
myJPanel.texto = ((JTextField)e.getSource()).getText();
// llamamos al metodo repaint para decirle a nuestro
// JPanel que vuelva a dibujarse, de esta forma se
// ejecutara nuestro metodo sobreescrito paint en la
// clase MyJPanel
myJPanel.repaint();
}
});
// aqui creamos una instancia de nuestro JPanel
// personalizado usando el constructor por defecto
myJPanel = new MyJPanel();
// agregamos nuestro campo de texto a nuestra ventana
this.getContentPane().add(campo, BorderLayout.NORTH);
// agregamos nuestro JPanel personalizado a nuestra ventana
this.getContentPane().add(myJPanel, BorderLayout.CENTER);
// establecemos tamaño y visibilidad de nuestra ventana
this.setSize(500,300);
this.setVisible(true);
}
public static void main(String args[]){
// aqui comienza nuestro programita
// lo hacemos creando nuestra ventana MyJFrame
MyJFrame frame = new MyJFrame();
// para que se termine el programa al cerrar la ventana
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
Si quieres ver el ejemplo funcionando, copia este código en dos archivos llamados MyJPanel.java y MyJFrame.java respectivamente, en un mismo folder, compila y ejecuta la clase MyJFrame. Espero que te sirva, suerte... Y por favor no olvides finalizar la pregunta.
1) MyJPanel: que es nuestro JPanel que reescribe al método paint y declara un atributo publico "public String texto" que puede ser usado desde cualquier otra clase. Aquí esta el código:
import javax.swing.*;
import java.awt.*;
// este es nuestro JPanel personalizado.
public class MyJPanel extends JPanel{
// este atributo es publico para que pueda ser
// usado desde la clase MyJFrame
public String texto;
// reescribimos el metodo paint
// este metodo es invocado cada vez que se requiera
// una actualizacion grafica de este JPanel
public void paint(Graphics g){
// primero dibujamos el fondo blanco
g.setColor(Color.white);
g.fillRect(0,0,this.getWidth(),this.getHeight());
// ahora dibujamos el String que se encuentra en la variable texto
g.setColor(Color.black);
if ( texto != null){
g.drawString(texto,10,20);
}
else {
// si la variable texto es nula, dibujamos entonces un mensaje
// amigable ;)
g.drawString("Hola, este es MyJpanel, cualquier cosa que escribas en el campo lo mostrare aqui",10,20);
}
}
}
2) MyJFrame: que es la ventana que nos permite ejecutar el ejemplo y ver nuestro JPanel funcionando. Aquí esta el código:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class MyJFrame extends JFrame {
// este es nuestro JPanel personalizado
private MyJPanel myJPanel;
public MyJFrame(){
// un campo de texto que usaremos para dibujar, lo que el usuario
// escriba en el, sobre nuestro JPanel.
JTextField campo = new JTextField("Escriba algo aqui");
// agregamos un oyente de evento de teclado
campo.addKeyListener(new KeyAdapter(){
// lo que se ponga en el cuerpo de este metodo
// se ejecutara cada vez que una tecla sea liberada
// sobre nuestro campo de texto.
public void keyReleased(KeyEvent e){
// pasamos el texto escrito en nuestro campo a la variable
// texto definida en nuestra clase MyJPanel
myJPanel.texto = ((JTextField)e.getSource()).getText();
// llamamos al metodo repaint para decirle a nuestro
// JPanel que vuelva a dibujarse, de esta forma se
// ejecutara nuestro metodo sobreescrito paint en la
// clase MyJPanel
myJPanel.repaint();
}
});
// aqui creamos una instancia de nuestro JPanel
// personalizado usando el constructor por defecto
myJPanel = new MyJPanel();
// agregamos nuestro campo de texto a nuestra ventana
this.getContentPane().add(campo, BorderLayout.NORTH);
// agregamos nuestro JPanel personalizado a nuestra ventana
this.getContentPane().add(myJPanel, BorderLayout.CENTER);
// establecemos tamaño y visibilidad de nuestra ventana
this.setSize(500,300);
this.setVisible(true);
}
public static void main(String args[]){
// aqui comienza nuestro programita
// lo hacemos creando nuestra ventana MyJFrame
MyJFrame frame = new MyJFrame();
// para que se termine el programa al cerrar la ventana
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
Si quieres ver el ejemplo funcionando, copia este código en dos archivos llamados MyJPanel.java y MyJFrame.java respectivamente, en un mismo folder, compila y ejecuta la clase MyJFrame. Espero que te sirva, suerte... Y por favor no olvides finalizar la pregunta.
Gracias por responder, esto fue lo que hice
public class Panel extends JPanel {
public Color color;
public int posX;
public int posY;
public int ancho;
public int alto;
public Panel(){
super();
}
public void paint(Graphics g){
g.setColor(color);
g.fillRect(posX, posY, ancho, alto);
repaint();
}
// en a clase JFrame
public MiFrame JFrame
public Panel mipanel;
MiFrame (){
mipanel = new Penel();
//Llamo a un método donde se actualizan los valores que recibirá mipanel, desde ese método
//Llamo a mipanel.repaint();
// Y así casa vez que vayan a actualizar los valores
el panel esta agregado al frame y se hace setvisible el frame
}
Pero cuando lo corro no aparece nada de mi panel.
¿Qué estoy haciendo mal?
public class Panel extends JPanel {
public Color color;
public int posX;
public int posY;
public int ancho;
public int alto;
public Panel(){
super();
}
public void paint(Graphics g){
g.setColor(color);
g.fillRect(posX, posY, ancho, alto);
repaint();
}
// en a clase JFrame
public MiFrame JFrame
public Panel mipanel;
MiFrame (){
mipanel = new Penel();
//Llamo a un método donde se actualizan los valores que recibirá mipanel, desde ese método
//Llamo a mipanel.repaint();
// Y así casa vez que vayan a actualizar los valores
el panel esta agregado al frame y se hace setvisible el frame
}
Pero cuando lo corro no aparece nada de mi panel.
¿Qué estoy haciendo mal?
El problema es que estas llamando al método repaint dentro de tu método paint, que es el peor lugar donde puedes hacer esto, ya que al llamar al método repaint le estas diciendo a tu JPanel que se vuelva a pintar, que es lo que acabas de hacer en tu método paint... es es lo que se llama un loop... así que lo que te recomiendo es que quites la linea que llama al método repaint de tu método paint de tal forma que quede así:
public void paint(Graphics g){
g.setColor(color);
g.fillRect(posX, posY, ancho, alto);
repaint();
}
Nuevamente suerte y no olvides finalizar la pregunta
public void paint(Graphics g){
g.setColor(color);
g.fillRect(posX, posY, ancho, alto);
repaint();
}
Nuevamente suerte y no olvides finalizar la pregunta
No esta completo pero es la parte donde se hacen las llamadas, lo que trato de hacer en un tablero, este lo he logrado pintar en un jframe direto, en un jpanel no.
La declaración del jpanel la hizo el netbeans, ya que declare la clase jpanel y la agregue a la paleta de opciones y desde allá agregue un jpanel personalizado al jframe
Primero esta la clase del JPanel y luego esta la clase del JFrame
//clase del JPanel
public class Panel extends JPanel {
public int posX;
public int posY;
public int ancho;
public int alto;
public Color color;
@Override
public void paint(Graphics g){
g.setColor(color);
g.drawRect(posX, posY, ancho, alto);
}
public void pintar(int posX,int posY, int ancho, int alto, Color color){
this.posX=posX;
this.posY=posY;
this.ancho=ancho;
this.alto=alto;
this.color=color;
}
}
public class Miframe extends javax.swing.JFrame {
public XKlotski mijuego;
/** Creates new form Mifra */
public Miframe(){
initComponents();
mijuego = new XKlotski(); //Inicializa una instancia de una clase con muchos metodos
mijuego.cargarJuego("0"); //Inicializala matriz con los elementos a pintar
painter(); //Metodo iniciaa el proceso de seleccion de color para las piezas a pintar
}
public void painter(){
int posX,posY,ancho=40,alto=40;
Color col=null;
//Recorremos los elementos del mat
posY=40;
for(int i=0;i < 11;i++){
posX=40;
for(int j=0;j < 10; j++){
try {
//Escogemos el color a pintar segun el caracter (&,#,etc.)
if ((char)((XPieza) (mijuego.mat.getElemento(i, j))).getid_pieza() == '*') {
col = Color.red;
} else if (((char)((XPieza) (mijuego.mat.getElemento(i, j))).getid_pieza() >= 'a') && ((char)((XPieza) (mijuego.mat.getElemento(i, j))).getid_pieza() <= 'y')) {
col = Color.BLUE; //col=Color.yellow;
} else if ((char)((XPieza) (mijuego.mat.getElemento(i, j))).getid_pieza() == '#') {
col = Color.gray;
} else if ((char)((XPieza) (mijuego.mat.getElemento(i, j))).getid_pieza() == '-') {
col = Color.DARK_GRAY;
} else if ((char)((XPieza) (mijuego.mat.getElemento(i, j))).getid_pieza() == '&') {
col = Color.white;
} else if ((char)((XPieza) (mijuego.mat.getElemento(i, j))).getid_pieza() == ' ') {
col = Color.white;
}
if (((XPieza) (mijuego.mat.getElemento(i, j))).getid_pieza() == '.') {
col = Color.orange;
}
//Llamo a metodo que llama a pintar rectangulo
pintar(i, j, posX, posY, col);
posX += ancho;
} catch (XMatrizException ex) {
try {
throw new XMatrizException("Error al leer Matriz para pintar");
} catch (XMatrizException ex1) {
}
}
}
posY+=alto;
}
}
public void pintar(int i,int j,int posX,int posY, Color color){
int ancho=40,alto=40;
//Verificamos si tiene algun caracter igual arriba
if(i-1>=0){
if((char)((XPieza) (mijuego.mat.getElemento(i-1, j))).getid_pieza()!=(char)((XPieza) (mijuego.mat.getElemento(i, j))).getid_pieza()){
posY+=1;
alto-=1;
}
}
//Verificamos si tiene algun caracter igual a la izquierda
if(j-1>=0){
if((char)((XPieza) (mijuego.mat.getElemento(i, j-1))).getid_pieza()!=(char)((XPieza) (mijuego.mat.getElemento(i, j))).getid_pieza()){
posX+=1;
ancho-=1;
}
}
//Verificamos si tiene algun caracter igual abajo
if(i+1<mijuego.fil){
if((char)((XPieza) (mijuego.mat.getElemento(i+1, j))).getid_pieza()!=(char)((XPieza) (mijuego.mat.getElemento(i, j))).getid_pieza())
alto-=1;
}
//Verificamos si tiene algun caracter igual a la derecha
if(j+1<mijuego.col){
if((char)((XPieza) (mijuego.mat.getElemento(i, j+1))).getid_pieza()!=(char)((XPieza) (mijuego.mat.getElemento(i, j))).getid_pieza())
ancho-=1;
}
//llama a metodo del jpanel, se envian los valores para pintar.
mipanel.pintar(posX,posY,ancho,alto, color);
mipanel.repaint();
}
}
Espero lo entinedas.
La declaración del jpanel la hizo el netbeans, ya que declare la clase jpanel y la agregue a la paleta de opciones y desde allá agregue un jpanel personalizado al jframe
Primero esta la clase del JPanel y luego esta la clase del JFrame
//clase del JPanel
public class Panel extends JPanel {
public int posX;
public int posY;
public int ancho;
public int alto;
public Color color;
@Override
public void paint(Graphics g){
g.setColor(color);
g.drawRect(posX, posY, ancho, alto);
}
public void pintar(int posX,int posY, int ancho, int alto, Color color){
this.posX=posX;
this.posY=posY;
this.ancho=ancho;
this.alto=alto;
this.color=color;
}
}
public class Miframe extends javax.swing.JFrame {
public XKlotski mijuego;
/** Creates new form Mifra */
public Miframe(){
initComponents();
mijuego = new XKlotski(); //Inicializa una instancia de una clase con muchos metodos
mijuego.cargarJuego("0"); //Inicializala matriz con los elementos a pintar
painter(); //Metodo iniciaa el proceso de seleccion de color para las piezas a pintar
}
public void painter(){
int posX,posY,ancho=40,alto=40;
Color col=null;
//Recorremos los elementos del mat
posY=40;
for(int i=0;i < 11;i++){
posX=40;
for(int j=0;j < 10; j++){
try {
//Escogemos el color a pintar segun el caracter (&,#,etc.)
if ((char)((XPieza) (mijuego.mat.getElemento(i, j))).getid_pieza() == '*') {
col = Color.red;
} else if (((char)((XPieza) (mijuego.mat.getElemento(i, j))).getid_pieza() >= 'a') && ((char)((XPieza) (mijuego.mat.getElemento(i, j))).getid_pieza() <= 'y')) {
col = Color.BLUE; //col=Color.yellow;
} else if ((char)((XPieza) (mijuego.mat.getElemento(i, j))).getid_pieza() == '#') {
col = Color.gray;
} else if ((char)((XPieza) (mijuego.mat.getElemento(i, j))).getid_pieza() == '-') {
col = Color.DARK_GRAY;
} else if ((char)((XPieza) (mijuego.mat.getElemento(i, j))).getid_pieza() == '&') {
col = Color.white;
} else if ((char)((XPieza) (mijuego.mat.getElemento(i, j))).getid_pieza() == ' ') {
col = Color.white;
}
if (((XPieza) (mijuego.mat.getElemento(i, j))).getid_pieza() == '.') {
col = Color.orange;
}
//Llamo a metodo que llama a pintar rectangulo
pintar(i, j, posX, posY, col);
posX += ancho;
} catch (XMatrizException ex) {
try {
throw new XMatrizException("Error al leer Matriz para pintar");
} catch (XMatrizException ex1) {
}
}
}
posY+=alto;
}
}
public void pintar(int i,int j,int posX,int posY, Color color){
int ancho=40,alto=40;
//Verificamos si tiene algun caracter igual arriba
if(i-1>=0){
if((char)((XPieza) (mijuego.mat.getElemento(i-1, j))).getid_pieza()!=(char)((XPieza) (mijuego.mat.getElemento(i, j))).getid_pieza()){
posY+=1;
alto-=1;
}
}
//Verificamos si tiene algun caracter igual a la izquierda
if(j-1>=0){
if((char)((XPieza) (mijuego.mat.getElemento(i, j-1))).getid_pieza()!=(char)((XPieza) (mijuego.mat.getElemento(i, j))).getid_pieza()){
posX+=1;
ancho-=1;
}
}
//Verificamos si tiene algun caracter igual abajo
if(i+1<mijuego.fil){
if((char)((XPieza) (mijuego.mat.getElemento(i+1, j))).getid_pieza()!=(char)((XPieza) (mijuego.mat.getElemento(i, j))).getid_pieza())
alto-=1;
}
//Verificamos si tiene algun caracter igual a la derecha
if(j+1<mijuego.col){
if((char)((XPieza) (mijuego.mat.getElemento(i, j+1))).getid_pieza()!=(char)((XPieza) (mijuego.mat.getElemento(i, j))).getid_pieza())
ancho-=1;
}
//llama a metodo del jpanel, se envian los valores para pintar.
mipanel.pintar(posX,posY,ancho,alto, color);
mipanel.repaint();
}
}
Espero lo entinedas.
En tu código no veo la linea donde agregas el Panel al JFrame, supongo que eso lo haces en el método initComponents() de la clase Miframe ... pero deberías verificar que efectivamente el panel se esta agregando al ContentPane del frame... debería ser algo así:
this.getContentPane().add(mipanel, java.awt.BorderLayout.CENTER); // depende del Layout que estes usando
La otra cosa que te aconsejo es qepongas banderas en el método paint de tu Panel, de esa forma sabremos que es lo que se esta mandando a pintar, posiblemente hay alguna variable que esta haciendo que se pinte el rectángulo en un lugar donde no puede ser visible... yo haría esto:
public void paint(Graphics g){
System.out.println("banderas en metodo paint");
System.out.println(color = "+color);
g.setColor(color);
System.out.println("posX: "+posX+", posY: "+posY+", ancho: "+ancho+", alto: "+alto);
g.drawRect(posX, posY, ancho, alto);
}
Si después de hacer esto no se imprimen las banderas significa que el panel no esta siendo agregado al frame, así que debes revisar el código en tu método initComponents() ... eso es lo que se me ocurre para poder ayudarte a encontrar el problema... espero que mi respuesta te sirva de algo... suerte!
this.getContentPane().add(mipanel, java.awt.BorderLayout.CENTER); // depende del Layout que estes usando
La otra cosa que te aconsejo es qepongas banderas en el método paint de tu Panel, de esa forma sabremos que es lo que se esta mandando a pintar, posiblemente hay alguna variable que esta haciendo que se pinte el rectángulo en un lugar donde no puede ser visible... yo haría esto:
public void paint(Graphics g){
System.out.println("banderas en metodo paint");
System.out.println(color = "+color);
g.setColor(color);
System.out.println("posX: "+posX+", posY: "+posY+", ancho: "+ancho+", alto: "+alto);
g.drawRect(posX, posY, ancho, alto);
}
Si después de hacer esto no se imprimen las banderas significa que el panel no esta siendo agregado al frame, así que debes revisar el código en tu método initComponents() ... eso es lo que se me ocurre para poder ayudarte a encontrar el problema... espero que mi respuesta te sirva de algo... suerte!
- Compartir respuesta
- Anónimo
ahora mismo