Menú

Mostrar Mensajes

Esta sección te permite ver todos los mensajes escritos por este usuario. Ten en cuenta que sólo puedes ver los mensajes escritos en zonas a las que tienes acceso en este momento.

Mostrar Mensajes Menú

Mensajes - niano

#1
Hola.

Antes de nada muchas gracias por responder, rub'n.

Cita de: rub'n en 17 Mayo 2020, 17:44 PM

Bueno mira, respondiendo una parte de tu pregunta, seguro es incompatibilidad del Layout, porque el único Layout multiplataforma es el,

GroupLayout

Entonces como lo seteas a null, pues quizá este la cosa por ahi.


Mmmm... No sé si te he entendido bien. Resulta que el problema desapareció precisamente cuando metí la línea setLayout(null) al principio del constructor de la clase que extiende el JFrame, ¿dices que mejor haber hecho algo con un GroupLayout?

Un saludo y gracias.
#2
Hola.

Hace unos días solucioné el problema. Se trataba de incluir la línea setLayout(null); en el constructor del JFrame.

No entiendo muy bien por qué esa línea soluciona el problema. ¿A alguien se le ocurre por qué?

Me llama la atención especialmente que el error sólo ocurría en máquinas con Windows, lo he comprobado en dos diferentes. Sin embargo en máquinas con Mac el problema, según parece, no tenía lugar. Pero, ¿no se suponía que con el JPanel y el JFrame no dependían del sistema y que eso era una ventaja sobre el Canvas y el Frame?

Si alguien sabe algo sobre lo que pasa aquí me encantaría que me iluminase un poco. Supongo que ya se ve que estoy un poco verde en el tema y quizás no sea fácil explicármelo, pero estaría muy interesado en aprender algo al respecto.

Gracias de antemano. Un saludo.
#3
Java / Duda con interfaces gráficas en Java.
6 Septiembre 2019, 16:58 PM
Hola.

He tenido una pequeña sorpresa programando interfaces gráficas con Java. He simplificado el código manteniendo el problema para que se haga más sencilla su comprensión. Tenemos una clase Prueba2 que extiende un JFrame:

Código (java) [Seleccionar]

package prueba2;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.IOException;
import javax.swing.JFrame;
public class Prueba2 extends JFrame   {
    private PanelPrueba Juego;
    public Prueba2() throws IOException{
        Juego=new PanelPrueba();
        getContentPane().add(Juego);
        addWindowListener(new WindowAdapter(){
            public void windowClosing(WindowEvent e){
                System.exit(0);
            }
        });
       Juego.setVisible(true);
}
    public static void main(String[] args) throws IOException {
        Prueba2 J=new Prueba2();
        J.setBounds(0, 0, 400, 400);
        J.setVisible(true);
    }
}


Y otra clase PanelPrueba, que extiende un JPanel e implementa un KeyListener:

Código (java) [Seleccionar]

package prueba2;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import static javax.swing.JOptionPane.PLAIN_MESSAGE;
import static javax.swing.JOptionPane.YES_NO_OPTION;
import static javax.swing.JOptionPane.YES_OPTION;
import static javax.swing.JOptionPane.showConfirmDialog;
import javax.swing.JPanel;

public class PanelPrueba extends JPanel implements KeyListener {
    public PanelPrueba(){
        setBounds(0,0,200,500);
        addKeyListener(this);
        setFocusable(true);
        requestFocus();
}
    public void paint(Graphics g){
        g.setColor(Color.WHITE);
        g.fillRect(0, 0, 200, 500);
    }
    public void reiniciar() {
        repaint();
    }
    @Override
    public void keyTyped(KeyEvent que) {}
   
    @Override
    public void keyPressed(KeyEvent que)  {
        if(showConfirmDialog(this,"Has ganado,deseas empezar otra partida?","Fin de Partida",YES_NO_OPTION,PLAIN_MESSAGE)==YES_OPTION){
            reiniciar();
        } 
        else{
           System.exit(0);
        }
    }
   
    @Override
    public void keyReleased(KeyEvent que) {}
}


Básicamente lo que pasa cuando aprietas una tecla es que te sale un cuadro de diálogo con dos botones. Si se pulsa "No" la aplicación finaliza y si se pulsa "Sí" vuelve a la situación inicial. La sorpresa está en que si se pulsa "Sí" aparece un molesto texto detrás del JPanel. ¿Alguien sabría explicarme por qué pasa eso, y cómo se puede solucionar el problema?

He estado probando cosas, y si el cuadro de diálogo haces que aparezca con un showMessageDialog en lugar de con un showConfirmDialog el problema desaparece.

Por otro lado, si hago que la clase PanelPrueba extienda un Canvas en lugar de un JPanel el problema desaparece. No obstante, quisiera solucionar el problema con un JPanel, ya que éste es el "peso pesado" de los contenedores, y aporta muchas ventajas, ¿verdad?  ;)

También me gustaría comentar que me han pasado cosas parecidas cuando he añadido objetos de clases JPanel y JButton a un mismo JFrame, y que estos problemas han desaparecido igualmente utilizando Canvas.

Agradezco de antemano cualquier tipo de ayuda o comentario y el tiempo que os haya tomado atenderme.

Un saludo a todos.
#4
Hola rub'n.

Antes de nada muchas gracias por tu respuesta, me ha sido muy útil. He hecho los cambios que me has indicado y ya funciona todo perfectamente. No obstante, me gustaría hacer un par de preguntas y observaciones si no te importa.

Cita de: rub'n en 11 Julio 2019, 16:08 PM

Tu Panel extiende de Canvas, debería ser de JPanel, ambos se aplica lo mismo para obtener el foco, cuando haces click obtienes el focu del panel que contiene los eventos del KeyListener dog.


¿Te importaría indicarme, aunque sea por encima, qué ventajas tiene la clase JPanel sobre la Canvas? Según tengo entendido la clase JPanel es más nueva y todo eso. Además, es cierto que con la Canvas sigue sin funcionar el asunto. Lo que sucede es que la clase JPanel creo que no la controlo demasiado. Tampoco sé lo que es un dog  :huh:

En otro ejercicio que me planteé parecido a este, si utilizaba la clase JPanel me empezaban a salir componentes como botones y cuadros de texto sobre el panel si hacía algo con ellos, cuando en un principio debían estar fuera. ¿Qué te parece?¿Sabrías decirme por qué me podía estar pasando eso? Con la Canvas no me pasaba y por eso renegué de la clase JPanel. Leeré algo más sobre la JPanel a ver si me familiarizo un poco más con ella.

Cita de: rub'n en 11 Julio 2019, 16:08 PM
Por ningun lado vi a

Código (java) [Seleccionar]
addKeyListener(this);

lo añadí en el método iniciar, entonces al darle click se habilita el KeyListener y el foco de ese Panel con

Código (java) [Seleccionar]
requestFocus();

Sí, tienes toda la razón, se me olvidó lo del addKeyListener cuando escribí el mensaje, aunque sí que lo tenía en mi código, dentro del constructor de la clase Panel.

Supongo que la clave para solucionar el problema está en lo del requestFocus(). No conocía ese método. Si lo quito los métodos de la KeyListener no se activan, por muchos 'clicks' que haga. Sin embargo, si utilizo una Canvas, es indiferente ponerlo o no ponerlo. Para que se ejecuten los métodos del KeyListener hay que hacer 'click'. ¿Sabes por qué? ¿O sabes dónde puedo encontrar información sobre todo esto? Me temo que el material que tengo es bastante corto para responderme a todas las preguntas que me surgen cuando pongo las cosas en práctica.

Por otro lado, dentro del detener:
.
Cita de: rub'n en 11 Julio 2019, 16:08 PM
Código (java) [Seleccionar]

public void detener() {
    play = false;
    removeKeyListener(this);
}


¿Qué hace ese removeKeyListener? ¿Es necesario? No lo había visto nunca, en mi corta experiencia en estos asuntos.

Y para finalizar, añadir que me has dado una buena idea con la modificación del windowClosing para que el programa confirme que realmente se quiere salir. Empiezo ahora también con los cuadros de diálogo. A ver si poco a poco me voy aclarando.

Y eso, que muchísimas gracias por todo, en serio. Un saludo.
#5
Hola.

Soy algo novato en todo esto de las interfaces gráficas y animaciones y tengo algunas dudas con un código en Java que estoy confeccionando. Necesito crear una animación controlada por cuatro teclas del teclado que empiece o se detenga cuando se aprieta un botón con el ratón.

Para eso defino utilizo una clase a la que he llamado Panel:

Código (java) [Seleccionar]

public class Panel extends Canvas implements Runnable, KeyListener{

    //Atributos:
   private int ancho, alto; //el alto y el ancho del panel
    private boolean play=false;//Variable que nos indica si la animación ha comenzado o no.
   //... Más atributos. En general, objetos que deben ser pintados. Y variables que indican lo que
    //tienen que hacer esos objetos durante la animación
   
    //Constructor:
   public Panel(int anch, int alt)
    {
         ancho=anch;
         alto=alt;
         play=false;
         //Se construyen los demás atributos
    }

    public void paint (Graphics G)
    {
         //Aquí se pintan algunos de los atributos del objeto utilizando técnicas de doble bouffering
    }

    public void update (Graphics G)
    {
        paint (G);
    }
   
    public void actualizar()
    {
        //Nada.. Aquí se actualiza la posición de los objetos (atributos de Panel) que deben ser
        //pintados durante la animación
    }

    public void run()
    {
        while (play)
        {
            actualizar();
            repaint();
            try
            {
                Thread.sleep((int)espera);
            }
            catch (InterruptedException E)
            {}
            //Y más cosas que no creo que vengan a cuento.
        }
    }
    public void Iniciar()
    {
        play=true;
        Thread hilo=new Thread(this);
        hilo.start();
    }
    public void Detener()
    {
        play=false;
    }
    //Metodos de KeyListener
    public void keyTyped(KeyEvent e) {
    }
    public void keyPressed(KeyEvent e)
    {
        if (e.getKeyChar()=='a')
        {
            //Se modifican los atributos necesarios para que la animación haga lo que tiene que
            //hacer cuando se pulsa una 'a'
        }
        if (e.getKeyChar()=='s')
        {
            //Lo mismo para la 's'
        }
        if (e.getKeyChar()=='l')
        {
            //...
        }
        if (e.getKeyChar()=='ñ')
        {
            //...
        }
    }

    @Override
    public void keyReleased(KeyEvent e)
    {
        if (e.getKeyChar()=='a')
        {
            //Se modifican los atributos necesarios para que la animación haga lo que tiene que
            //hacer cuando se suelta la 'a'
        }
        if (e.getKeyChar()=='s')
        {
           //...
        }
        if (e.getKeyChar()=='l')
        {
           //...
        }
        if (e.getKeyChar()=='ñ')
        {
            //...
        }
    }

}


Y otra clase, la clase Juego2:

Código (java) [Seleccionar]

public class Juego2 extends JFrame implements ActionListener
{
    private Panel P;
    private JButton boton;
    private boolean play=false;
    private int anchoP=900, altoP=700;

    //El constructor. No creo que tenga mucho interés para lo de mi duda pero lo pongo por si
    //acaso:
    public Juego2()
    {
        P=new Panel (anchoP,altoP);
        boton=new JButton("play");
        setBackground(new Color(240,240,240));
        setLayout(null);       
        boton.addActionListener(this);
       
        getContentPane().add(boton);
        boton.setBounds(20,330,250,30);
       
        getContentPane().add(P);
        P.setBounds(300, 30, anchoP, altoP);
        P.setVisible(true);
       
        addWindowListener(new WindowAdapter(){
            public void windowClosing(WindowEvent e){
                System.exit(0);
            }
        });
    }

    //el main
    public static void main(String[] args) {
        final Juego2 F = new Juego2();
        F.setBounds(0, 0, 1300, 800);
        F.setVisible(true);
    }

    //El actionPerformed de la clase ActionListener
    public void actionPerformed(ActionEvent e) {
        if (e.getSource()==boton)
        {
            if (play)
            {
                play=false;
                boton.setText("play");
                P.Detener();
            }
            else
            {
                play=true;
                boton.setText("pause");
                P.Iniciar();
            }
        }
    }
}


A continuación explicaré el fenómeno que me crea dudas.Cuando el código está listo hago lo siguiente:

1) Ejecuto el código. La cosa va bien, todo se construye y se visualiza correctamente.
2) Le doy al play. Y la animación comienza correctamente.
3) Le doy a una de las teclas controladoras y no ocurre nada. ¡Nada de nada!
4) Hago un 'click' de ratón sobre el panel y desde entonces ya sí funciona todo bien. El 'click' tiene que ser sobre el panel, si lo hago sobre otro punto de la ventana o fuera de ella las teclas controladoras siguen inactivas.

¿Alguien sabe por qué pasa esto y cómo puedo solucionarlo? Es decir, me gustaría que las teclas controladoras funcionasen desde que le doy al play, que no fuese necesario hacer ese 'click'.

Muchas gracias de antemano por vuestro tiempo. Un saludo.
#6
Java / Re: Simulación gráfica animada
7 Julio 2019, 17:26 PM
Hola NEBIRE.

Vale sí, claro, claro, lo entiendo, lo entiendo. Muy interesante esto de empezar pensando si el acceso es síncrono o aleatorio para usar una lista enlazada o un array, sobre todo si la dimensión de la estructura puede hacerse muy grande. Aquí, en principio no quería utilizar el programilla este para simular una situación con un gran número de bolas, así que creo que lo voy a dejar así, de momento, pero gracias por el consejo. Lo tendré en cuenta para futuras batallas.  ;)

Un saludo.
#7
Java / Re: Simulación gráfica animada
7 Julio 2019, 00:09 AM
Hola NEBIRE. (Editado. Había escrito mal el nick)

Antes de nada, gracias por tu tiempo y por tus sabios consejos. Soy prácticamente nuevo en POO, en Java y en interfaces gráficas, así que toda ayuda es más que bienvenida por mi parte. Mira, te comento alguna cosilla más.

En este hilo en el que estamos publiqué el código que tenía entonces. La mayoría de las cosas que hice en él relacionadas con botones, paneles, casillas de activación, ratón y cosas de esas fueron un tanto arbitrarias. Las metí a partir de ejemplos que fui viendo por aquí y por allá y al final me quedó un batiburrillo bastante elegante.

Unos días después publiqué otro hilo en este mismo foro que también enlacé en mi respuesta anterior. Ese código está algo más evolucionado, ya que he ido entendiendo las cosas de porqué esto y porqué lo otro, o al menos a mí eso me parece. Estaría encantado de que me lo criticases también, aunque sea a vuelapluma, ya que tengo versiones posteriores del código en las que se han ido mejorando cosillas y con lo que estoy aprendiendo es fácil que en las próximas semanas el código sufra otras muchas otras modificaciones. Pero vamos, que todo comentario es bienvenido.

No entiendo lo que dices de que toda acción con una lista enlazada es síncrona. ¿Te importaría explicarme un poquillo ese concepto? Gracias. He manejado listas enlazadas cuando aprendí a programar. Eso fue en C. C puro, sin el ++  :D y entiendo lo que son listas enlazadas. Lo que no entiendo es lo de que las acciones sobre ellas sean síncronas.

Disculpa que no haya dejado nada claro el enunciado. Es un ejemplo que he pillado por ahí y que me gustaría reproducir grosso modo para aprender un poco sobre esto de interfaces gráficas, gráficos, animaciones... No hace falta que lo reproduzca de manera exacta.

Gracias por todo y un saludo ;).
#8
Java / Re: Simulación gráfica animada
5 Julio 2019, 10:26 AM
Hola.

Solucionado aquí

Un saludo.
#9
Hola.

Vale, ya está solucionado. Resulta que en el ActionPerformed de la clase Aplicacion llamaba al constructor de PanelCercles para construir de nuevo a Panel, un atributo de la clase Aplicacion que ya se había construído en el constructor de esta última clase. Se ve que eso no le gustaba al método mouseMoved de la clase PanelCercles, que aún funcionaba con los parámetros del Panel anterior. No entiendo muy bien por qué pasa esto, si alguien me lo pudiese explicar se lo agradecería.

La solución ha sido crear un método public void reiniciar(int n) en la clase PanelCercles que lo que hace es asignar el atributo Nbolas=n y construir un nuevo array bolas[] de este nuevo tamaño. De esta manera, el ActionPerformed puede llamar a este método sin necesidad de volver a construir el Panel.

Un saludo, y gracias.
#10
Hola muy buenas a todos y a todas.

Antes de nada quisiera aclarar que soy algo nuevo en el foro y tengo poca experiencia en cuanto a exponer dudas sobre códigos. He estado sobre esto en alguno de los posts que hay en el foro y agradezco cualquier sugerencia que me hagáis encaminada a conseguir que ayudarme sea una tarea sencilla.

Hace unos días publiqué una duda en este hilo. Abro un nuevo hilo para ver si resulta algo más interesante y también para comentar que la cosa ha ido avanzando, aunque todavía me queda un pequeño problema por solucionar. Vuelvo a enlazar aquí un vídeo con un ejemplo con lo que debo conseguir. Aquí va el código completo de las clases que he creado para el ejercicio:

Clase Aplicacion:
Código (java) [Seleccionar]

/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package practica.pkg2;



import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.IOException;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JTextField;


/**
*
* @author joseb
*/
public  class Aplicacion  extends JFrame implements ItemListener,ActionListener{
   
   
   
   private JCheckBox Check1;
   private JCheckBox Check2;
   private JTextField Text;
   private PanelCercles Panel;
   /**
    *
    */
   

   
   public   Aplicacion(){
       Panel= new PanelCercles(5,false,false,380,680,new vector(0,0));
       
       this.getContentPane().setBackground(new Color(240,240,240));

       Text=new JTextField();
       Check1=new JCheckBox("With Walls");
       Check2=new JCheckBox("Follow mouse");
     
       Check1.addItemListener(this);
       Check2.addItemListener(this);
       Text.addActionListener(this);
     
       getContentPane().setLayout(null);
     
       getContentPane().add(Text);
       Text.setBounds(20,20,250,30);
       
       getContentPane().add(Check1);
       Check1.setBounds(20, 70, 250, 30);
       
       getContentPane().add(Check2);
       Check2.setBounds(20, 120, 250, 30);
       
       getContentPane().add(Panel);
       Panel.setBounds(300, 30, 700, 400);
       
       addWindowListener(new WindowAdapter(){
           public void windowClosing(WindowEvent e){
               System.exit(0);
           }
       });
       
       
       
       
       
       
       
   }
   
   @Override
   public void itemStateChanged(ItemEvent E){
       if(E.getItemSelectable()==Check1){
           Panel.cambiar_walls(Check1.isSelected());            
           
       }
       if(E.getItemSelectable()==Check2){
           Panel.cambiar_mouse(Check2.isSelected());
           
           if (Check2.isSelected()==false)
           {
               Panel.reiniciarAceleraciones();
           }
       }
       
   }
   
   /**
    *
    * @param A
    */
   @Override
   public void actionPerformed(ActionEvent A){  
       if (A.getSource()==Text)
       {
           int n =Integer.parseInt(Text.getText());
           vector c=new vector (0,0);
           c.cambiarx(Panel.obtCentro().obtenerx());
           c.cambiary(Panel.obtCentro().obtenery());
           Panel= new PanelCercles(n,Check1.isSelected(),Check2.isSelected(),380,680,c);
           getContentPane().setLayout(null);
           getContentPane().add(Panel);
           Panel.setBounds(300, 30, 700, 400);
       }
       
   }    
   public void bucle() throws IOException
   {
       
       Panel.actualizar_Bolas();
       Panel.repaint();
   }
   /**
    *
    * @param Args
    */
   public static void main (String Args[]) throws InterruptedException, IOException{
      final Aplicacion F = new Aplicacion();
       
       F.setBounds(0, 0, 1300, 800);
       F.setVisible(true);
     
       while (1==1)
       {
           F.bucle();
           F.setVisible(true);
           Thread.sleep((long)50);
       }
  }
}



Clase PanelCercles
Código (java) [Seleccionar]

/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package practica.pkg2;

import java.awt.Color;
import java.awt.Graphics;

import java.awt.event.MouseEvent;
import static java.awt.event.MouseEvent.MOUSE_MOVED;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.io.IOException;
import javax.swing.JPanel;


/**
*
* @author joseb
*/
public  class PanelCercles extends JPanel implements MouseMotionListener {
 
private Cercle[] bolas;
private int Nbolas;
private boolean with_walls;
private boolean followmouse;
private vector centro;
private int alto;
private int ancho;


   public PanelCercles(int Nbols, boolean walls, boolean mouse, int alt, int anch, vector cen){
   vector v,p,a;
   centro=new vector (cen.obtenerx(),cen.obtenery());
   followmouse=mouse;
   with_walls=walls;
   alto=alt;
   ancho=anch;
   setSize(ancho,alto);
   setBackground(Color.WHITE);
   a=new vector(0,1);
   Nbolas=Nbols;
   bolas= new Cercle[Nbolas];
       for (int i =0;i<Nbolas;i++){
       p=new vector((int)(Math.random()*ancho),(int)(Math.random()*alto));
       v=new vector((int)(Math.random()*10-5),(int)(Math.random()*10)-5);
       Color c=new Color((int)(Math.random()*255),(int)(Math.random()*255),(int)(Math.random()*255));
       
       bolas [i]=new Cercle(20,a,v,c,p);
   }
   addMouseMotionListener(this);
}

   /**
    *
    * @param G
    */
@Override
   public void paint(Graphics G){
       G.setColor(Color.WHITE);
       G.fillRect(0, 0, 1500,1500);
        for(int i=0;i<Nbolas;i++){
       bolas[i].dibujar(G,true);
       
   }
   for(int i=0;i<Nbolas;i++){
       bolas[i].dibujar(G,false);
       
   }
   
   
}
 
public void actualizar_Bolas() throws IOException{
   
   for (int i=0;i<Nbolas;i++){
     
       bolas[i].actualizar(alto, ancho, with_walls, followmouse, centro);
       //System.out.printf("Centro: ("+obtCentro().obtenerx()+","+obtCentro().obtenery()+")\n\n");
       //System.out.printf("Has actualizado la bola "+i+" "+followmouse+"\n");

       
   }
}
@Override
public void mouseDragged(MouseEvent e){}

@Override
public void mouseMoved(MouseEvent e){
   //System.out.printf("Estas moviendo el ratón: "+followmouse+"\n");
   if(followmouse==true){
       //System.out.printf("Entras??\n");
       centro.cambiarx(e.getX());
       centro.cambiary(e.getY());

   }  
}
 
public void cambiar_mouse(boolean m){
   followmouse=m;
}
public void cambiar_walls(boolean w){
   with_walls=w;
}
public void reiniciarAceleraciones()
{
   for (int i=0;i<Nbolas;i++){      
       bolas[i].initAceleracion();          
   }

}
public vector obtCentro()
{
   return centro;
}

//
public boolean obtFollowm()
{
   return followmouse;
}

}


Clase Cercle
Código (java) [Seleccionar]

/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package practica.pkg2;

import java.awt.Color;
import java.awt.Graphics;

/**
*
* @author joseb
*/
public class Cercle {
   
   private int diametre;
   private Color col;
   private vector velocitat;
   private vector acceleracio;
   private vector posicio;
   private vector anterior;


public Cercle(int diam,vector accel, vector vel, Color color, vector pos){
diametre= diam;
col=color;
posicio=pos;
acceleracio=accel;
velocitat=vel;
anterior=new vector(0,0);

}    
   
   public void controlar(int alto,int ancho,boolean with_walls){
       boolean sentido=false;
       if (velocitat.obtenerx()>=0)
       {
           sentido=true;
       }
       if(posicio.obtenerx()>ancho && with_walls==false){
           posicio.cambiarx(posicio.obtenerx()-ancho);          
           
       }
       if(posicio.obtenerx()<0 && with_walls==false){
           posicio.cambiarx(posicio.obtenerx()+ancho);          
           
       }
       if(posicio.obtenery()>alto && with_walls==false){
           posicio.cambiary(posicio.obtenery()-alto);          
           
       }
       if(posicio.obtenery()<0 && with_walls==false){
           posicio.cambiary(posicio.obtenery()+alto);          
           
       }

       if(posicio.obtenerx()>ancho && with_walls==true){
           posicio.cambiarx(-posicio.obtenerx()+2*ancho);
           velocitat.cambiarx(-velocitat.obtenerx());
           
       }
       if(posicio.obtenerx()<0 && with_walls==true){
           posicio.cambiarx(-posicio.obtenerx());  
           velocitat.cambiarx(-velocitat.obtenerx());
           
       }
       if(posicio.obtenery()>alto && with_walls==true){
           posicio.cambiary(-posicio.obtenery()+2*alto);
           velocitat.cambiary(-velocitat.obtenery());
           
       }
       if(posicio.obtenery()<0 && with_walls==true){
           posicio.cambiary(-posicio.obtenery());
           velocitat.cambiary(-velocitat.obtenery());
           
       }
       if (velocitat.limitaciomod(20))
       {
           if (sentido&&velocitat.obtenerx()==0)
           {
               velocitat.cambiarx(2);
           }
           if (!sentido&&velocitat.obtenerx()==0)
           {
               velocitat.cambiarx(-2);
           }

       }

   }
   public void actualizar(int alto,int ancho,boolean with_walls,boolean followmouse,vector puntero){
       double k=0.1;
       anterior.cambiarx(posicio.obtenerx());
       anterior.cambiary(posicio.obtenery());
     
       if(followmouse){
           acceleracio.cambiarx(puntero.obtenerx());
           acceleracio.cambiary(puntero.obtenery());
           acceleracio.resta(posicio);
           acceleracio.multiplicacion(k);
           
       }
       
       velocitat.suma(acceleracio);
       
       posicio.suma(velocitat);
       
       controlar(alto,ancho,with_walls);
       
       
   }
   public void dibujar(Graphics pincel, boolean blanco){
      if(blanco==true){
       Color d=new Color (255,255,255);
       pincel.setColor(d);
       pincel.fillOval(anterior.obtenerx(), anterior.obtenery(), diametre, diametre);
       pincel.drawOval(anterior.obtenerx(), anterior.obtenery(), diametre, diametre);  
      }
       

      else{
       pincel.setColor(col);
       pincel.fillOval(posicio.obtenerx(), posicio.obtenery(), diametre, diametre);
       
       Color c = new Color(0,0,0);
       pincel.setColor(c);
       pincel.drawOval(posicio.obtenerx(), posicio.obtenery(), diametre, diametre);
      }
   }
   
   public vector obtenerAceleracion ()
   {
       return  acceleracio;
   }
   public vector obtenerVelocidad (){
      return velocitat;
   }
   public vector obtenerPosicion(){
      return posicio;
   }
   public vector obtenerAnterior(){
      return anterior;
   }
   public void initAceleracion()
           
   {
       acceleracio=new vector(0,1);
   }

}



Clase vector
Código (java) [Seleccionar]

/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package practica.pkg2;

import static java.lang.Math.sqrt;

/**
*
* @author joseb
*/
public class vector {

private int x;
private int y;


public vector(int posx, int posy){
x=posx;
y=posy;

}

   vector() {
       throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
   }
public void suma(vector a){
 x=a.x+x;
 y=a.y+y;    
}

public void resta(vector a){
 x=x-a.x;
 y=y-a.y;    
}


public void multiplicacion(double k){
   
 x=(int) (k*x);
 y=(int) (y*k);
   
}
public void division(double k){
   
 x=(int) (x/k);
 y=(int) (y/k);
   
}



public double modulo(){
   return  sqrt(x*x+y*y);
   
}

public void unitari(){
   division(modulo());
}

public boolean limitaciomod(double Max){
   if(modulo()>Max){
       multiplicacion(Max/modulo());
       return true;
       
   }
   return false;
}
/*
public void limitaciox(int with_walls,int ancho){
   if(x>ancho)
   
}*/
public  int obtenerx(){
   return x;
}
public  int obtenery(){
   
   return y;
}
public void cambiarx(int nueva){
   x=nueva;
}
public void cambiary(int nueva){
   y=nueva;
}

}


El programa empieza bien. Responde correctamente al cambio de estado de las casillas de activación y al movimiento del puntero del ratón sobre el panel de bolas. Cuando en el cuadro de texto cambio del número de bolas también hace lo correcto, es decir, crear un nuevo panel con ese número de bolas y las visualiza correctamente. No obstante, después de cambiar ese parámetro, el programa no responde bien al cambio de estado de la casilla de activación "Follow mouse".

No alcanzo a entender dónde está el problema. Creo que está relacionado con la gestión de eventos de ratón. En concreto el método mouseMoved de la clase PanelCercles funciona de una manera un tanto aleatoria. Sí que se ejecuta cuando toca, pero el parámetro booleano followmouse lo lee de manera un tanto aleatoria (o eso es lo que a mí, dentro de mi ignorancia, me parece). Además, cuando lo lee como true entra en el condicional para cambiar el parámetro centro pero no lo hace. Insisto en que el problema sólo aparece después de cambiar, al menos una vez, el número de bolas en el cuadro de texto correspondiente.

He puesto una serie de "printf"s ocultos al compilador para que si ejecutáis el código y quitáis las barras // veáis lo que os digo. Esos "printf"s están en las líneas 81, 82, 92 y 94 de la clase PanelCercles.

El primero de ellos es para mostrar que el atributo centro no cambia.
El segundo es para mostrar que en este punto del código el atributo followmouse es correcto. Es decir, corresponde con el estado de la casilla de activación "Follow mouse".
El tercero es para mostrar que en este punto el atributo followmouse puede cambiar en relación al punto anterior. Su estado aquí es aleatorio, a veces toma el valor true y a veces el valor false, y no cambia con el estado de la casilla de activación correspondiente.
El cuarto es para mostrar que a veces entra en el condicional en el que se debería cambiar el atributo centro, pero como se ve en el primer "printf" no lo hace.

En fin, estoy algo perdido con esto. ¿Cómo lo veis vosotros? ¿Tenéis alguna sugerencia o idea. Utilizo el NetBeans en un Windows 10.

Agradezco de antemano cualquier tipo de comentario o de ayuda. Un saludo.