26 julio, 2011

Controlar JSpinner con la rueda del mouse

Una caracteristica de una buena aplicacion con interfaz gráfica es la capacidad de responder a eventos que el usuario supone debe realizar para una determinada acción.

Me explico: Si un usuario ve un botón, la acción natural es hacer clic en el, pero también sería válido hacer que el botón responda a la tecla 'enter'.

Del mismo modo, en los JSpinner la acción natural es utilizar las flechitas y hacer clic en ellas para modificar el valor, pero si el mouse tiene rueda probablemente el usuario girará la rueda esperando modificar el valor del JSpinner.

Para que esto ocurra, se debe agregar al JSpinner un listener que implemente la interfaz MouseWheelListener. Java tiene por defecto una implementación vacía llamada MouseAdapter que simplifica la creación de listener ya que debe sobrecargarse sólo el método que necesitamos.

Manos a la obra: Una vez instanciado nuestro JSpinner agregamos un MouseAdapter con un código similar a éste:

JSpinner spinner = new JSpinner();
SpinnerModel modelo = new SpinnerNumberModel(0, 0, 100, 1);
spinner.setModel(modelo);
spinner.addMouseWheelListener(new MouseAdapter() {


    @Override
    public void mouseWheelMoved(MouseWheelEvent e) {
        try {
            Object mov = null;
            if (e.getWheelRotation() == 1) {
                //la rueda baja
                mov = modelo.getPreviousValue();
            } else if (e.getWheelRotation() == -1) {
                //la rueda sube
                mov = modelo.getNextValue();
            }
            if (mov == null) {
                return;
            }
            modelo.setValue(mov);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
});


Como puede observarse, se agrega una clase anónima que extiende a MouseAdapter y sobrecargamos el método mouseWheelMoved(). En este método leemos el evento y determinamos la dirección en que se giró la rueda. Para ello invocamos el método getWheelRotation() que retornará un entero: -1 si la rueda "sube" y 1 si la rueda "baja".

Luego, sabiendo la direccion en que el usuario giró la rueda, le solicitamos al modelo del JSpinner el valor siguiente o anterior según el caso. Cuando se ha llegado al tope de valores del modelo (0 o 100 en el ejemplo) el modelo retorna null.

Teniendo el valor que debemos aplicar, se lo entregamos al modelo. Fin del problema.

Se pueden hacer varias mejoras al ejemplo (por ejemplo usar un switch en lugar de un if, pero eso queda a gusto del programador)

No hay comentarios.: