Buscar
Social
Ofertas laborales ES

Foro sobre Java SE > Mover grafico en un JPanel desde otro JPanel

Hola, buenas noches. Tengo una duda, sobre cómo puedo enlazar un JPanel con otro. Tengo basicamente 2 paneles, un JPanel en donde muestro el grafico, y otro que sera el JPanel donde estarán los botones para mover el gráfico (un círculo).

He creado las propiedades altura y lados como variables de clase (He puesto dos clases internas para los 2 JPanel) para que las dos clases internas puedan acceder a ellas.

Cada evento de los 4 botones, aumenta o decrementa las propiedades altura o lados, esto para que se mueva el círculo hacia arriba, abajo, derecha o izquierda. Y aquí es donde surge el problema, no logro llamar al metodo paint del JPanel que tiene el gráfico desde los eventos de los botones.

Código:

circleButton;


import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.FlowLayout;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.EmptyBorder;

public class BolaMoviblePorBoton extends JFrame{

private int altura = 160;
private int lados = 230;

public static void main(String... algo){
SwingUtilities.invokeLater(new Runnable(){
@Override
public void run(){
new BolaMoviblePorBoton();
}
});
}
public BolaMoviblePorBoton(){
init();
}
private void init(){
try{
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName() );
}
catch(ClassNotFoundException | IllegalAccessException | InstantiationException | UnsupportedLookAndFeelException e){
JOptionPane.showMessageDialog(null,e.toString());
}
JFrame app = new JFrame();
app.setLayout(new BorderLayout());
PanelGrafico panel = new PanelGrafico();
panel.setBackground(Color.ORANGE);
app.add(panel,BorderLayout.CENTER);
app.add(new PanelBotones().getBotones(),BorderLayout.SOUTH);
app.setTitle("Bola Movible");
app.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
app.setSize(550,550);
app.setResizable(false);
app.setVisible(true);
}
public class PanelGrafico extends JPanel {

@Override
public void paint(Graphics g){
super.paint(g);
Graphics2D graphics = (Graphics2D) (g);
// establece antialiasing (bordes finos)
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
graphics.setColor(Color.black);
graphics.fillOval(lados, altura, 100, 100);
}
public void dibujar(){
this.repaint();
}
}
public class PanelBotones extends JPanel {

public JPanel getBotones(){
final PanelGrafico pnl = new PanelGrafico();
JPanel botones = new JPanel(new FlowLayout());
JPanel botonesContenedor = new JPanel(new BorderLayout());
botones.setBackground(Color.white);
botones.setBorder(new EmptyBorder(30,60,0,60));
botonesContenedor.setBackground(Color.white);
botonesContenedor.setPreferredSize(new Dimension(550,100));
botonesContenedor.add(botones,BorderLayout.CENTER);

JButton bi = new JButton("Izquierda");
bi.setPreferredSize(new Dimension(90,35));
bi.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
lados-=10;
pnl.dibujar();
}
});
botones.add(bi);

JButton bd = new JButton("Derecha");
bd.setPreferredSize(new Dimension(90,35));
bd.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
lados+=10;
pnl.dibujar();
}
});
botones.add(bd);


JButton ba = new JButton("Debajo");
ba.setPreferredSize(new Dimension(90,35));
ba.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
altura += 10;
pnl.dibujar();
}
});
botones.add(ba);


JButton bs = new JButton("Arriba");
bs.setPreferredSize(new Dimension(90,35));
bs.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
altura -= 10;
pnl.dibujar();
}
});
botones.add(bs);

return botonesContenedor;
}
}
} // end class.

Muchas gracias por la ayuda.

octubre 16, 2013 | Unregistered CommenterSomeone

PanelGrafico panel = new PanelGrafico();

Es una variable local del método init(), por eso no puedes acceder.

octubre 16, 2013 | Registered Commenterchoces

Hola, gracias por responder :)

Ya lo declaré como propiedad de la clase PanelBotones y sigue el problema.

Acabo de darle varios clics a la izquierda, y cuando muevo la ventana debajo de la barra de tareas y la vuelvo a subir, se actualiza el gráfico. El gráfico no se actualiza automáticamente como debería de ser. Vi por allí que colocando un Thread.sleep() se actualizaba el gráfico rápido, pero sucede lo mismo. En pocas palabras, el gráfico no se actualiza, hasta que mueva la ventana fuera de escritorio.


Gracias de antemano.

octubre 16, 2013 | Unregistered CommenterSomeone

¿Con qué método actualizas el JPanel?.
Deberías usar repaint();

Y eso de que lo declaras como una propiedad del otro... me suena extraño.

Por otra parte, deberías sobreescribir
public void paintComponent(Graphics g)
y no paint(Graphics g)

octubre 16, 2013 | Registered Commenterchoces

Disculpa choces, me equivoqué. La propiedad panel ya no la declaré en el método init, como me sugeriste, también cambié a paintComponent. Te dejo el nuevo code con las modificaciones :)

Código:
<Code>
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.FlowLayout;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.EmptyBorder;

public class BolaMoviblePorBoton extends JFrame{
PanelGrafico panel = new PanelGrafico();
private int altura = 160;
private int lados = 230;

public static void main(String... algo){
SwingUtilities.invokeLater(new Runnable(){
@Override
public void run(){
new BolaMoviblePorBoton();
}
});
}
public BolaMoviblePorBoton(){
init();
}
private void init(){
try{
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName() );
}
catch(ClassNotFoundException | IllegalAccessException | InstantiationException | UnsupportedLookAndFeelException e){
JOptionPane.showMessageDialog(null,e.toString());
}
JFrame app = new JFrame();
app.setLayout(new BorderLayout());
panel.setBackground(Color.ORANGE);
app.add(panel,BorderLayout.CENTER);
app.add(new PanelBotones().getBotones(),BorderLayout.SOUTH);
app.setTitle("Bola Movible");
app.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
app.setSize(550,550);
app.setResizable(false);
app.setVisible(true);
}
public class PanelGrafico extends JPanel {

@Override
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D graphics = (Graphics2D) (g);
// establece antialiasing (bordes finos)
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
graphics.setColor(Color.black);
graphics.fillOval(lados, altura, 100, 100);
}
public void dibujar(){
repaint();
System.out.println("Valor de altura: \t"+altura+"\nValor de lados: \t"+lados);
}

}
public class PanelBotones extends JPanel {
PanelGrafico pnl = new PanelGrafico();

public JPanel getBotones(){

JPanel botones = new JPanel(new FlowLayout());
JPanel botonesContenedor = new JPanel(new BorderLayout());
botones.setBackground(Color.white);
botones.setBorder(new EmptyBorder(30,60,0,60));
botonesContenedor.setBackground(Color.white);
botonesContenedor.setPreferredSize(new Dimension(550,100));
botonesContenedor.add(botones,BorderLayout.CENTER);

JButton bi = new JButton("Izquierda");
bi.setPreferredSize(new Dimension(90,35));
bi.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
lados-=10;
pnl.repaint();
}
});
botones.add(bi);

JButton bd = new JButton("Derecha");
bd.setPreferredSize(new Dimension(90,35));
bd.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
lados+=10;
pnl.repaint();
}
});
botones.add(bd);


JButton ba = new JButton("Debajo");
ba.setPreferredSize(new Dimension(90,35));
ba.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
altura += 10;
pnl.repaint();
}
});
botones.add(ba);


JButton bs = new JButton("Arriba");
bs.setPreferredSize(new Dimension(90,35));
bs.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
altura -= 10;
pnl.repaint();
}
});
botones.add(bs);

return botonesContenedor;
}
}
} // end class.


Si uso: pnl.repaint(); o pnl.dibujar(); para actualizar el JPanel, da exactamente el mismo resultado.

Me parece raro que se actualice el JPanel cuando saco el JFrame fuera de la pantalla.


Gracias nuevamente :)

octubre 16, 2013 | Unregistered CommenterSomeone

Tuve que salir, pero una vez que ya he vuelto, échale un par de ojos al código modificado siguiente, que funciona correctamente:


public class BolaMoviblePorBoton extends JFrame {

public static void main(String... algo) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new BolaMoviblePorBoton();
}
});
}
private PanelGrafico panel;
private int altura;
private int lados;

public BolaMoviblePorBoton() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | IllegalAccessException | InstantiationException | UnsupportedLookAndFeelException e) {
JOptionPane.showMessageDialog(null, e.toString());
}
this.lados = 230;
this.altura = 160;
this.panel = new PanelGrafico();
JFrame app = new JFrame();
app.setLayout(new BorderLayout());
panel.setBackground(Color.ORANGE);
app.add(panel, BorderLayout.CENTER);
app.add(new PanelBotones().getBotones(), BorderLayout.SOUTH);
app.setTitle("Bola Movible");
app.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
app.setSize(550, 550);
app.setResizable(false);
app.setVisible(true);
}

public class PanelGrafico extends JPanel {

@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D graphics = (Graphics2D) (g);
// establece antialiasing (bordes finos)
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
graphics.setColor(Color.black);
graphics.fillOval(lados, altura, 100, 100);
}

public void dibujar() {
repaint();
System.out.println("Valor de altura: \t" + altura + "\nValor de lados: \t" + lados);
}
}

public class PanelBotones extends JPanel {

public JPanel getBotones() {

JPanel botones = new JPanel(new FlowLayout());
JPanel botonesContenedor = new JPanel(new BorderLayout());
botones.setBackground(Color.white);
botones.setBorder(new EmptyBorder(30, 60, 0, 60));
botonesContenedor.setBackground(Color.white);
botonesContenedor.setPreferredSize(new Dimension(550, 100));
botonesContenedor.add(botones, BorderLayout.CENTER);

JButton bi = new JButton("Izquierda");
bi.setPreferredSize(new Dimension(90, 35));
bi.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
lados -= 10;
panel.repaint();
}
});
botones.add(bi);

JButton bd = new JButton("Derecha");
bd.setPreferredSize(new Dimension(90, 35));
bd.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
lados += 10;
panel.repaint();
}
});
botones.add(bd);


JButton ba = new JButton("Debajo");
ba.setPreferredSize(new Dimension(90, 35));
ba.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
altura += 10;
panel.repaint();
}
});
botones.add(ba);


JButton bs = new JButton("Arriba");
bs.setPreferredSize(new Dimension(90, 35));
bs.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
altura -= 10;
panel.repaint();
}
});
botones.add(bs);

return botonesContenedor;
}
}
} // end class.

octubre 16, 2013 | Registered Commenterchoces

Otra manera de crear la clase, usando NetBeans:

package swing;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JPanel;

public class BolaMoviblePorBoton extends javax.swing.JFrame {

private int altura;
private int lados;

/** Creates new form BolaMoviblePorBoton */
public BolaMoviblePorBoton() {

this.lados = 180;
this.altura = 120;

initComponents();

jButtonIzquierda.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
lados -= 10;
jPanelGrafico.repaint();
}
});
jButtonDerecha.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
lados += 10;
jPanelGrafico.repaint();
}
});
jButtonAbajo.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
altura += 10;
jPanelGrafico.repaint();
}
});
jButtonArriba.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
altura -= 10;
jPanelGrafico.repaint();
}
});
}

/** This method is called from within the constructor to
initialize the form.
WARNING: Do NOT modify this code. The content of this method is
always regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {

jPanelGrafico = new PanelGrafico();
jButtonIzquierda = new javax.swing.JButton();
jButtonDerecha = new javax.swing.JButton();
jButtonAbajo = new javax.swing.JButton();
jButtonArriba = new javax.swing.JButton();

setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
setPreferredSize(new java.awt.Dimension(460, 430));

jPanelGrafico.setBackground(new java.awt.Color(255, 153, 51));

javax.swing.GroupLayout jPanelGraficoLayout = new javax.swing.GroupLayout(jPanelGrafico);
jPanelGrafico.setLayout(jPanelGraficoLayout);
jPanelGraficoLayout.setHorizontalGroup(
jPanelGraficoLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 0, Short.MAX_VALUE)
);
jPanelGraficoLayout.setVerticalGroup(
jPanelGraficoLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 334, Short.MAX_VALUE)
);

jButtonIzquierda.setText("Izquierda");

jButtonDerecha.setText("Derecha");

jButtonAbajo.setText("Abajo");

jButtonArriba.setText("Arriba");

javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jPanelGrafico, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addGap(0, 104, Short.MAX_VALUE)
.addComponent(jButtonIzquierda)
.addGap(18, 18, 18)
.addComponent(jButtonDerecha)
.addGap(18, 18, 18)
.addComponent(jButtonAbajo)
.addGap(18, 18, 18)
.addComponent(jButtonArriba)))
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(jPanelGrafico, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(18, 18, 18)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jButtonIzquierda)
.addComponent(jButtonDerecha)
.addComponent(jButtonAbajo)
.addComponent(jButtonArriba))
.addContainerGap())
);

pack();
}// </editor-fold>

/**
@param args the command line arguments
*/
public static void main(String args[]) {
/* Set the Nimbus look and feel */
//<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
/* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
* For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
*/
try {
for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
javax.swing.UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | javax.swing.UnsupportedLookAndFeelException ex) {
java.util.logging.Logger.getLogger(BolaMoviblePorBoton.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
}
//</editor-fold>

/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
new BolaMoviblePorBoton().setVisible(true);
}
});
}

private class PanelGrafico extends JPanel {

@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D graphics = (Graphics2D) (g);
// establece antialiasing (bordes finos)
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
graphics.setColor(Color.black);
graphics.fillOval(lados, altura, 100, 100);
}
}
// Variables declaration - do not modify
private javax.swing.JButton jButtonAbajo;
private javax.swing.JButton jButtonArriba;
private javax.swing.JButton jButtonDerecha;
private javax.swing.JButton jButtonIzquierda;
private javax.swing.JPanel jPanelGrafico;
// End of variables declaration }
}

octubre 16, 2013 | Registered Commenterchoces

Funciona correctamente como quería choces, muchas gracias. ¿Podrías decirme el por qué sucedía lo anterior y por qué ahora utilizando el objeto PanelGrafico para llamar a repaintya no pasa?


Muchas gracias amigo.

octubre 16, 2013 | Unregistered CommenterSomeone

Creabas el panel gráfico dentro de la clase para los botones, pero no lo añadías a ningún panel, ni al frame, sino que lo iniciabas dentro del cargador de la clase de los botones.
Al iniciarse, se dibuja y se muestra; pero no hace nada más, porque las acciones se dirigen a un panel local sin contenedor. Cuando se redibuja el frame, después de minimizarse, se revalida todo su contenido, por eso se veía el movimiento en ese caso.

Por eso te comentaba que era raro declararlo como variable local. Al declararlo como variable global, se resuelve el problema, incluso sin haberlo añadido a un contenedor. Tampoco es muy ortodoxo, por eso creé de nuevo el frame con NetBeans, donde sí se añade a un contenedor.

octubre 16, 2013 | Registered Commenterchoces

Me quedó todo claro choces, muchas gracias por tu tiempo para ayudar a la nueva generación de Java Programmers :)

¿No has pensado en ser profesor de Universidad?

octubre 16, 2013 | Registered CommenterJFK

Se me ha pasado el arroz para ser profesor, aparte de que no me gusta ;D
Tampoco creo que ninguna Universidad me contratase, dicho sea de paso.

octubre 16, 2013 | Registered Commenterchoces

Estás siendo demasiado humilde choces. Serías un excelente profesor, tienes muy buena didáctica.

Saludos amigo, y gracias de nuevo.

octubre 16, 2013 | Registered CommenterJFK