1

我的班级没有从选择的颜色变化时Event Controller从中收到事件,也没有收到(我正在使用的那个星星)。我已经彻底检查过,但找不到问题,这是我的代码(为方便起见,我省略了包和导入):JColorChooserKeyEventsJComponent

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;
}
}  
4

1 回答 1

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);
}

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

在您AreaDeDibujos的班级中,您已覆盖paint,但未能调用super.paint。这些paint方法是一组复杂的例程,除非您有充分的理由这样做,否则您真的不想破坏它们。

您应该paintComponent改用(并且不要忘记调用super.paintComponent)。如果没有其他原因,那么事实paintComponent就是双缓冲而paint不是。

This will, also, mean you don't need to use g.setColor or g.clearRect as the super paint methods will take care of it for you.

于 2013-02-07T05:42:22.950 回答