Eventos de ratón y cuadros de texto en Java

Iniciado por niano, 4 Julio 2019, 09:56 AM

0 Miembros y 1 Visitante están viendo este tema.

niano

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.

niano

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.