某些组件对事件没有响应

时间:2013-02-07 05:28:39

标签: java swing events focus

我的Event Controller班级在其所选颜色发生变化时未收到来自JColorChooser的活动,也未从KeyEvents收到JComponent(我是{I}}用来画星星)。我已经彻底检查过,但是找不到问题,这是我的代码(为方便起见,我省略了包和导入):

public class Main {

public static void main(String[] args) {
    GestorDeEventos ge=new GestorDeEventos();

    Interfaz f=new Interfaz();

    ge.setVentana(f);
    f.setGestorEventos(ge);
}
}

public class Interfaz extends JFrame {

private GestorDeEventos miGestor;

private Container c;

AreaDeDibujos lienzo;

private JLabel lInfo,lCantidadPuntas,lTamanioEstrella,lLargoPuntas,lColor,lRotar;
JSpinner spinnerCantidadPuntas;
JSlider sliderTamanioEstrella;
DoubleJSlider sliderLargoPuntas;
JColorChooser ccColor;
JButton bRotarIzquierda,bRotarDerecha;
public Interfaz(){

    setTitle("Ejemplo <<Dibujo de primitivas y poligonos>> Version 1.1 (07/02/2013)");
    setSize(1024,720);
    setResizable(false);

    c=getContentPane();
    c.setBackground(new Color(240,250,245));
    c.setLayout(null);

    lienzo=new AreaDeDibujos(600,600);
    lienzo.setLocation(400,15);

    c.add(lienzo);

    // Para informar al usuario del proposito de dicha seccion de la interfaz
    lInfo=new JLabel("Por favor, seleccione los parametros de la estrella a dibujar:");
    lInfo.setBounds(10,10,350,20);
    c.add(lInfo);

    // Para seleccionar la cantidad de puntas de la estrella
    lCantidadPuntas=new JLabel("Numero de puntas de la estrella: ");
    lCantidadPuntas.setBounds(10,35,350,20);
    c.add(lCantidadPuntas);
    spinnerCantidadPuntas=new JSpinner(new SpinnerNumberModel(7, //valor inicial
                                                              Estrella.MINIMO_PUNTAS, //valor minimo
                                                              Estrella.MAXIMO_PUNTAS, //valor maximo
                                                              1 // incremento/decremento (paso)
                                                             )
                                       );
    spinnerCantidadPuntas.setBounds(10,55,120,20);
    /*
      En la siguiente linea deshabilito el campo de texto del JSPinner de modo que su valor
      solo pueda ser editado mediante los botones que incluye el propio JSpinner, esto lo hago
      para evitar que alguien coloque un valor fuera del rango [Estrella.MINIMO_PUNTAS, Estrella.MAXIMO_PUNTAS]
    */
    ((JSpinner.DefaultEditor)spinnerCantidadPuntas.getEditor()).getTextField().setEditable(false);
    c.add(spinnerCantidadPuntas);

    //Para seleccionar el tamaño de la estrella
    lTamanioEstrella=new JLabel("Tamaño de la estrella (pixeles): ");
    lTamanioEstrella.setBounds(10,80,350,20);
    c.add(lTamanioEstrella);
    sliderTamanioEstrella=new JSlider( 
                                     JSlider.HORIZONTAL,
                                     AreaDeDibujos.TAMANIO_ESTRELLA_MINIMO,
                                     AreaDeDibujos.TAMANIO_ESTRELLA_MAXIMO,
                                     (int)(AreaDeDibujos.TAMANIO_ESTRELLA_MAXIMO/2)
                                     );
    Hashtable etiquetasDelSlider1 = new Hashtable();
    int i,cantidadDeRayas,rango,paso,minimo,maximo,valorDeLaRaya;
    minimo=AreaDeDibujos.TAMANIO_ESTRELLA_MINIMO;
    maximo=AreaDeDibujos.TAMANIO_ESTRELLA_MAXIMO;
    rango=maximo-minimo;
    cantidadDeRayas=10;
    paso=rango/cantidadDeRayas;
    for(i=0;i<=cantidadDeRayas;i++){
        valorDeLaRaya=minimo+paso*i;
        etiquetasDelSlider1.put(new Integer (valorDeLaRaya), new JLabel(""+valorDeLaRaya));
    }
    sliderTamanioEstrella.setLabelTable( etiquetasDelSlider1 );
    sliderTamanioEstrella.setPaintLabels(true);
    sliderTamanioEstrella.setMajorTickSpacing(paso);
    sliderTamanioEstrella.setPaintTicks(true);
    sliderTamanioEstrella.setBounds(10,100,350,60);
    c.add(sliderTamanioEstrella);

    //Para seleccionar el largo de las puntas de la estrella (% con respecto al tamaño total de la estrella)
    lLargoPuntas= new JLabel("Largo de las puntas(%): ");
    lLargoPuntas.setToolTipText("(% con respecto al tamaño total de la estrella)");
    lLargoPuntas.setBounds(10,165,350,20);
    c.add(lLargoPuntas);

    sliderLargoPuntas=new DoubleJSlider(100, 900, 367, 1000);
    Hashtable etiquetasDelSlider2 = new Hashtable();
    minimo=100;
    maximo=900;
    rango=maximo-minimo;
    cantidadDeRayas=10;
    paso=rango/cantidadDeRayas;
    for(i=0;i<=cantidadDeRayas;i++){
        valorDeLaRaya=minimo+paso*i;
        etiquetasDelSlider2.put(new Integer (valorDeLaRaya), new JLabel(""+valorDeLaRaya/10));
    }
    sliderLargoPuntas.setLabelTable( etiquetasDelSlider2 );
    sliderLargoPuntas.setPaintLabels(true);
    sliderLargoPuntas.setMajorTickSpacing(paso);
    sliderLargoPuntas.setPaintTicks(true);
    sliderLargoPuntas.setBounds(10,185,350,60);
    c.add(sliderLargoPuntas);

    // Para seleccionar el color
    lColor=new JLabel("Color: ");
    lColor.setBounds(10,250,350,20);
    c.add(lColor);
    ccColor=new JColorChooser(new Color(0,255,255));
    ccColor.setPreviewPanel(new JPanel());
    JScrollPane spColor=new JScrollPane(ccColor);
    spColor.setBounds(10,270,350,250);
    c.add(spColor);

    //Para rotar la estrella
    lRotar=new JLabel("Rotar: ");
    lRotar.setBounds(10,525,350,20);
    c.add(lRotar);

    bRotarIzquierda=new JButton("<");
    bRotarIzquierda.setBounds(63,545,80,40);
    c.add(bRotarIzquierda);

    bRotarDerecha=new JButton(">");
    bRotarDerecha.setBounds(206,545,80,40);
    c.add(bRotarDerecha);

    setFocusable(true);
    setVisible(true);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setLocationRelativeTo(null);
}

public void setGestorEventos(GestorDeEventos ge){
    miGestor=ge;
    spinnerCantidadPuntas.addChangeListener(miGestor);
    sliderLargoPuntas.addChangeListener(miGestor);
    sliderTamanioEstrella.addChangeListener(miGestor);
    ccColor.getSelectionModel().addChangeListener(miGestor);

    bRotarDerecha.addActionListener(miGestor);
    bRotarIzquierda.addActionListener(miGestor);

    lienzo.addKeyListener(miGestor);
    /*addKeyListener(miGestor);
    spinnerCantidadPuntas.addKeyListener(miGestor);
    sliderLargoPuntas.addKeyListener(miGestor);
    sliderTamanioEstrella.addKeyListener(miGestor);
    ccColor.addKeyListener(miGestor);
    bRotarDerecha.addKeyListener(miGestor);
    bRotarIzquierda.addKeyListener(miGestor);*/
}

}

public class AreaDeDibujos extends JComponent {

public static final int TAMANIO_ESTRELLA_MINIMO=50,TAMANIO_ESTRELLA_MAXIMO=400;
private DibujoDeEstrella dibujo;

public AreaDeDibujos(int largo, int ancho){
    setFocusable(true);
    setSize(largo,ancho);
    setBackground(Color.WHITE);
}

@Override
public void paint(Graphics g){
    g.setColor(Color.WHITE);
    g.clearRect(0, 0, this.getWidth(), this.getHeight());
    if(dibujo!=null){
        g.setColor(dibujo.getColor());
        for(Polygon d: dibujo.getDibujos())
            g.fillPolygon(d);
    }        
}

public void pintarEstrella(DibujoDeEstrella d){
    dibujo=d;
    repaint();
}
}

public class GestorDeEventos implements ChangeListener,KeyListener,ActionListener {

Interfaz ventana;
AreaDeDibujos areaDeTrabajo;

DibujoDeEstrella dibujo;

public GestorDeEventos() {
}

public void setVentana(Interfaz ventana) {
    this.ventana = ventana;
    areaDeTrabajo= ventana.lienzo;
    dibujo=new DibujoDeEstrella(
                               new Estrella(
                                           ventana.sliderTamanioEstrella.getValue(),
                                           (int)ventana.spinnerCantidadPuntas.getValue(),
                                           ventana.sliderLargoPuntas.getScaledValue(),
                                           ventana.ccColor.getColor()
                                           )
                               );
    areaDeTrabajo.pintarEstrella(dibujo);
}

@Override
public void stateChanged(ChangeEvent e) {
    if(e.getSource()==ventana.sliderLargoPuntas){
        dibujo.setLargoDePuntas(ventana.sliderLargoPuntas.getScaledValue());
    }
    else if(e.getSource()==ventana.sliderTamanioEstrella){
        dibujo.setTamanio(ventana.sliderTamanioEstrella.getValue());

    }
    else if(e.getSource()==ventana.spinnerCantidadPuntas){
        dibujo.setCantidadPuntas((int)ventana.spinnerCantidadPuntas.getValue());

    }
    else if(e.getSource()==ventana.ccColor){
        dibujo.setColor(ventana.ccColor.getColor());
    }
    areaDeTrabajo.pintarEstrella(dibujo);
}

@Override
public void keyTyped(KeyEvent e) { //NO USADA, AL NO DECLARAR NADA ADENTRO ESTAMOS EFECTIVAMENTE
                                   //IGNORANDO TODOS LOS EVENTOS DE ESTE TIPO
}

@Override
public void keyPressed(KeyEvent e) {
    if(e.getKeyCode()==KeyEvent.VK_LEFT){
        dibujo.moverIzquierda();
    }
    else if(e.getKeyCode()==KeyEvent.VK_RIGHT){
        dibujo.moverDerecha();
    }
    else if(e.getKeyCode()==KeyEvent.VK_UP){
        dibujo.moverArriba();
    }
    else if(e.getKeyCode()==KeyEvent.VK_DOWN){
        dibujo.moverAbajo();
    }
    areaDeTrabajo.pintarEstrella(dibujo);
}

@Override
public void keyReleased(KeyEvent e) { //NO USADA, AL NO DECLARAR NADA ADENTRO ESTAMOS EFECTIVAMENTE
                                      //IGNORANDO TODOS LOS EVENTOS DE ESTE TIPO
}

@Override
public void actionPerformed(ActionEvent e) {
    if(e.getSource().equals(ventana.bRotarIzquierda)){
        dibujo.rotar(-1);
    }
    else if(e.getSource().equals(ventana.bRotarDerecha)){
        dibujo.rotar(1);
    }
    areaDeTrabajo.pintarEstrella(dibujo);
}

}

public class DibujoDeEstrella {

private Estrella miEstrella; //Aqui guardamos los datos de la estrella como tal (independiente de como la dibujaremos)

private LinkedList<Polygon> dibujos; //Esto es lo que entregaremos al JComponent para que dibuje la estrella

/* Las siguientes variables sirven para generar el dibujo a partir de la estrella, en ellas
   contemplamos parametros como lo son el angulo actual de la estrella, la posicion actual dentro
   del JComponent, y los puntos de los 2 circulos que usamos para construir el dibujo, todas usadas
   para crear los poligonos LISTOS PARA SER DIBUJADOS
*/
private int posicionActualX,posicionActualY;
private double anguloActual,circuloInteriorX[],circuloInteriorY[],circuloExteriorX[],
               circuloExteriorY[],radioDelCirculoInterior,radioDelCirculoExterior,
               gradosEntreCadaPunto,anguloEntrePuntos,anguloInicial,desplazamiento;
public DibujoDeEstrella(Estrella e){
    miEstrella=e;
    posicionActualX=0;
    posicionActualY=0;
    anguloActual=0.0;
}

private void crearDibujo(){
    calcularCirculos();
    int i;
    dibujos=new LinkedList<Polygon>(); //El centro + cada una de las puntas
    //creamos el centro de una sola vez y lo introducimos dentro de la lista de poligonos a dibujar
    dibujos.add(crearCentro());
    Polygon punta;
    for(i=0;i<circuloExteriorX.length;i++){
        punta=new Polygon();
        punta.addPoint((int)circuloInteriorX[i], (int)circuloInteriorY[i]);
        punta.addPoint((int)circuloExteriorX[i], (int)circuloExteriorY[i]);
        if(i+1<circuloExteriorX.length)
            punta.addPoint((int)circuloInteriorX[i+1], (int)circuloInteriorY[i+1]);
        else
            punta.addPoint((int)circuloInteriorX[0], (int)circuloInteriorY[0]);
        dibujos.add(punta);
    }
}

private Polygon crearCentro(){
    int cx[],cy[],cantidadDePuntos;
    cantidadDePuntos=miEstrella.getCantidadPuntas();
    cx=new int[cantidadDePuntos];
    cy=new int[cantidadDePuntos];
    int i=0;
    for(double x: circuloInteriorX)
        cx[i++]=(int)x;
    i=0;
    for(double y: circuloInteriorY)
        cy[i++]=(int)y;
    return new Polygon(cx,cy,cantidadDePuntos);
}

private void inicializarVariables(){
    //Para nosotros es mas facil y entendible trabajar con grados,
    //sin embargo las funciones de java trabajan con radianes
    gradosEntreCadaPunto=360.0/miEstrella.getCantidadPuntas();

    //para hacer el codigo mas corto y entendible crearemos una variables mas
    //donde esten los angulos que necesitamos en radianes
    anguloEntrePuntos=Math.toRadians(gradosEntreCadaPunto);
    anguloInicial=Math.toRadians(anguloActual);
    desplazamiento=anguloEntrePuntos/2;

    radioDelCirculoExterior=miEstrella.getTamanioPixeles()/2;
    radioDelCirculoInterior=radioDelCirculoExterior*miEstrella.getLargoDePuntas();
}

private void calcularCirculos(){
    circuloInteriorX= new double[miEstrella.getCantidadPuntas()];
    circuloInteriorY= new double[miEstrella.getCantidadPuntas()];
    circuloExteriorX= new double[miEstrella.getCantidadPuntas()];
    circuloExteriorY= new double[miEstrella.getCantidadPuntas()];
    int i;
    double anguloDelPunto;
    for(i=0;i<circuloInteriorX.length;i++){
        anguloDelPunto=anguloInicial+i*anguloEntrePuntos;
        circuloInteriorX[i]=(double)posicionActualX+ radioDelCirculoInterior*Math.cos(anguloDelPunto);
        circuloInteriorY[i]=(double)posicionActualY+ radioDelCirculoInterior*Math.sin(anguloDelPunto);
        circuloExteriorX[i]=(double)posicionActualX+ radioDelCirculoExterior*Math.cos(desplazamiento+anguloDelPunto);
        circuloExteriorY[i]=(double)posicionActualY+ radioDelCirculoExterior*Math.sin(desplazamiento+anguloDelPunto);
    }
}

public LinkedList<Polygon> getDibujos() {
    crearDibujo();
    return dibujos;
}

public void rotar(int grados){
    anguloActual+=(double)grados;
    if(anguloActual>360.0)
        anguloActual-=360.0;
    else if(anguloActual<0.0)
        anguloActual+=360.0;
    anguloInicial=Math.toRadians(anguloActual);
    crearDibujo();
}

public void setCantidadPuntas(int cantidadPuntas) {
    miEstrella.setCantidadPuntas(cantidadPuntas);
    inicializarVariables();
}

public void setColor(Color color) {
    miEstrella.setColor(color);
}

public void setLargoDePuntas(double largoDePuntas) {
    miEstrella.setLargoDePuntas(largoDePuntas);
    inicializarVariables();
}

public Color getColor(){
    return miEstrella.getColor();
}

public void moverArriba(){posicionActualY-=10;}
public void moverAbajo(){posicionActualY+=10;}
public void moverIzquierda(){posicionActualX-=10;}
public void moverDerecha(){posicionActualX+=10;}

public void setTamanio(int t){
    miEstrella.setTamanioPixeles(t);
    inicializarVariables();
}
}

public class Estrella {

public static final int MINIMO_PUNTAS=3,MAXIMO_PUNTAS=10;

private int tamanioPixeles,cantidadPuntas;
private double largoDePuntas;
private Color color;

public Estrella(int tamanioPixeles, int cantidadPuntas, double largoDePuntas, Color color) {
    this.tamanioPixeles = tamanioPixeles;
    this.cantidadPuntas = cantidadPuntas;
    this.largoDePuntas = largoDePuntas;
    this.color = color;
}

public Estrella() {
}

public void setCantidadPuntas(int cantidadPuntas) {
    this.cantidadPuntas = cantidadPuntas;
}

public void setColor(Color color) {
    this.color = color;
}

public void setLargoDePuntas(double largoDePuntas) {
    this.largoDePuntas = largoDePuntas;
}

public void setTamanioPixeles(int tamanioPixeles) {
    this.tamanioPixeles = tamanioPixeles;
}

public int getCantidadPuntas() {
    return cantidadPuntas;
}

public Color getColor() {
    return color;
}

public double getLargoDePuntas() {
    return largoDePuntas;
}

public int getTamanioPixeles() {
    return tamanioPixeles;
}

}

class DoubleJSlider extends JSlider {

final int scale;

public DoubleJSlider(int min, int max, int value, int scale) {
    super(min, max, value);
    this.scale = scale;
}

public double getScaledValue() {
    return ((double)super.getValue()) / this.scale;
}
}  

1 个答案:

答案 0 :(得分:3)

您的第一个问题(颜色变化事件)更多地与您希望事件来自颜色选择器这一事实有关,尽管事实上您已将侦听器添加到颜色选择器的选择模型。

public void stateChanged(ChangeEvent e) {

    System.out.println("!! Ping !!" + e.getSource());

    if (e.getSource() == ventana.sliderLargoPuntas) {
        dibujo.setLargoDePuntas(ventana.sliderLargoPuntas.getScaledValue());
    } else if (e.getSource() == ventana.sliderTamanioEstrella) {
        dibujo.setTamanio(ventana.sliderTamanioEstrella.getValue());

    } else if (e.getSource() == ventana.spinnerCantidadPuntas) {
        dibujo.setCantidadPuntas((int) ventana.spinnerCantidadPuntas.getValue());

    // >>--- Change this ------------------------------------------------------------<<
    //} else if (e.getSource() == ventana.ccColor) {
    } else if (e.getSource() == ventana.ccColor.getSelectionModel()) {

        System.out.println("!! Pong !!");
        dibujo.setColor(ventana.ccColor.getColor());
    }
    areaDeTrabajo.pintarEstrella(dibujo);
}

你的第二个问题是对KeyListener的常见误解。强烈建议您不要使用KeyListener(出于您的原因),而是使用Key BindingsKeyListener仅在其附加的组件具有可关注性并且当前具有焦点时才有效。可以使用键绑定来克服此限制。

AreaDeDibujos课程中,您已覆盖paint,但无法拨打super.paintpaint方法是一组复杂的例程,除非你有充分的理由这样做,否则你真的不想破坏它们。

您应该使用paintComponent代替(并且不要忘记致电super.paintComponent)。如果没有其他原因,那么paintComponent是双重缓冲而paint不是。{/ p>

这也意味着您不需要使用g.setColorg.clearRect,因为超级油漆方法将为您处理。