miércoles, 21 de marzo de 2012

GradientPaint demo, ejemplos del uso de gradientes en java

Hoy hablaremos de los gradientes o degradados de color tan usados como relleno del fondo en multitud de situaciones.
Para ponernos en situación explicaremos primero que es un gradiente.
Básicamente un gradiente nos permite rellenar una forma con una degradación lineal del color. Es decir, si tenemos un punto A con un color X y un punto B con otro color Y, el espacio entre ambos puntos va cambiando progresivamente de color desde el color X al color Y.

Una vez aclarado esto, paso a enseñaros unos ejemplos del uso de gradientes. Para crearlos haremos uso de la clase GradientPaint que nos permite aplicar esta degradación de color entre 2 puntos que explicábamos arriba.
Los constructores de esta clase nos permiten especificar los 2 puntos y los 2 colores que utilizaremos para crear el gradiente.

GradientPaint gp = new GradientPaint(Point2D pt1, Color color1, Point2D pt2, Color color2, boolean cyclic);

Estos puntos podemos especificarlos mediante un objeto Point o bien mediante coordenadas:

GradientPaint gp = new GradientPaint(float x1, float y1, Color color1, float x2, float y2, Color color2, boolean cyclic);

El último parámetro indica si el gradiente debe repetirse en todo el espacio de manera cíclica o si fuera del espacio contenido entre ambos puntos el color debe ser sólido.

Pasamos ahora a ver algunos ejemplos del uso de gradientes.

Gradiente horizontal

package gradientPaintDemo;

import java.awt.Color;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;

import javax.swing.JPanel;

public class HorizontalGradientPanel extends JPanel {

 @Override
 public void paint(Graphics g) {
  Graphics2D g2d = (Graphics2D) g;

  /*
   * Para crear un gradiente horizontal,
   * las coordenadas a usar seran del {0,0} al {anchura del componente, 0}
   */
  GradientPaint horizontalGradient = new GradientPaint(0, 0, Color.RED, getWidth(), 0, Color.BLUE);
  g2d.setPaint(horizontalGradient);

  g2d.fillRect(0, 0, getWidth(), getHeight());

 }

}

Gradiente vertical

package gradientPaintDemo;

import java.awt.Color;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;

import javax.swing.JPanel;

public class VerticalGradientPanel extends JPanel {

 @Override
 public void paint(Graphics g) {
  Graphics2D g2d = (Graphics2D) g;

  /*
   * Para crear un gradiente vertical,
   * las coordenadas a usar seran del {0,0} al {0, altura del componente}
   */
  GradientPaint verticalGradient = new GradientPaint(0, 0, Color.GREEN, 0, getHeight(), Color.YELLOW);
  g2d.setPaint(verticalGradient);

  g2d.fillRect(0, 0, getWidth(), getHeight());

 }

}

Gradiente diagonal


package gradientPaintDemo;

import java.awt.Color;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;

import javax.swing.JPanel;

public class DiagonalGradientPanel extends JPanel {

 @Override
 public void paint(Graphics g) {
  Graphics2D g2d = (Graphics2D) g;

  /*
   * Para crear un gradiente diagonal,
   * las coordenadas a usar seran del {0,0} al {anchura del componente / ,
   * altura del componente / 2}
   */
  GradientPaint diagonalGradient = new GradientPaint(0, 0, Color.GRAY, getWidth() / 2, getHeight() / 2, Color.ORANGE);
  g2d.setPaint(diagonalGradient);

  g2d.fillRect(0, 0, getWidth(), getHeight());

 }

}

Gradiente redondo
Este degradado es un tanto especial, no usaremos la clase GradientPaint para crearlo, en lugar de eso implementaremos nuestro propio Paint. La interfaz Paint define como generar los patrones de color usados para operar con Graphics2D. Este ejemplo no es tan fácil de entender como los demás que exponemos en esta entrada, pero podéis reutilizar el código a placer.
package gradientPaintDemo;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Paint;
import java.awt.PaintContext;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.ColorModel;
import java.awt.image.Raster;
import java.awt.image.WritableRaster;

import javax.swing.JPanel;

public class RoundGradientPanel extends JPanel {

 @Override
 public void paint(Graphics g) {
  Graphics2D g2d = (Graphics2D) g;

  /* Para crear un gradiente circular. */
  RoundGradient roundGradient = new RoundGradient(getWidth() / 2, getHeight() / 2, Color.PINK, new Point(0, 100), Color.CYAN);
  g2d.setPaint(roundGradient);

  g2d.fillRect(0, 0, getWidth(), getHeight());
 }

 private class RoundGradient implements Paint {

  protected Point2D point;

  protected Point2D mRadius;

  protected Color color1, color2;

  public RoundGradient(double x, double y, Color color1, Point2D radius, Color color2) {
   if (radius.distance(0, 0) <= 0) {
    throw new IllegalArgumentException("Radius must be greater than 0.");
   }
   point = new Point2D.Double(x, y);
   this.color1 = color1;
   mRadius = radius;
   this.color2 = color2;
  }

  @Override
  public int getTransparency() {
   int a1 = color1.getAlpha();
   int a2 = color2.getAlpha();
   return (((a1 & a2) == 0xff) ? OPAQUE
          : TRANSLUCENT);
  }

  @Override
  public PaintContext createContext(ColorModel cm, Rectangle deviceBounds, Rectangle2D userBounds,
    AffineTransform xform, RenderingHints hints) {
   Point2D transformedPoint = xform.transform(point, null);
   Point2D transformedRadius = xform.deltaTransform(mRadius, null);
   return new RoundGradientContext(transformedPoint, color1, transformedRadius, color2);
  }

 }

 private class RoundGradientContext implements PaintContext {
  protected Point2D mPoint;

  protected Point2D mRadius;

  protected Color color1, color2;

  public RoundGradientContext(Point2D p, Color c1, Point2D r, Color c2) {
   mPoint = p;
   color1 = c1;
   mRadius = r;
   color2 = c2;
  }

  public void dispose() {
  }

  public ColorModel getColorModel() {
   return ColorModel.getRGBdefault();
  }

  public Raster getRaster(int x, int y, int w, int h) {
   WritableRaster raster = getColorModel().createCompatibleWritableRaster(w, h);

   int[] data = new int[w * h * 4];
   for (int j = 0; j < h; j++) {
    for (int i = 0; i < w; i++) {
     double distance = mPoint.distance(x + i, y + j);
     double radius = mRadius.distance(0, 0);
     double ratio = distance / radius;
     if (ratio > 1.0)
      ratio = 1.0;

     int base = (j * w + i) * 4;
     data[base + 0] = (int) (color1.getRed() + ratio * (color2.getRed() - color1.getRed()));
     data[base + 1] = (int) (color1.getGreen() + ratio * (color2.getGreen() - color1.getGreen()));
     data[base + 2] = (int) (color1.getBlue() + ratio * (color2.getBlue() - color1.getBlue()));
     data[base + 3] = (int) (color1.getAlpha() + ratio * (color2.getAlpha() - color1.getAlpha()));
    }
   }
   raster.setPixels(0, 0, w, h, data);

   return raster;
  }
 }

}


Gradiente horizontal cíclico

package gradientPaintDemo;

import java.awt.Color;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;

import javax.swing.JPanel;

public class HorizontalCyclicGradientPanel extends JPanel {

 @Override
 public void paint(Graphics g) {
  Graphics2D g2d = (Graphics2D) g;

  /*
   * Para crear un gradiente horizontal cíclico, simplemente especificar
   * la anchura del color
   * y crear el gradiente con la propiedad cíclica a "true"
   */
  GradientPaint diagonalGradient = new GradientPaint(0, 0, Color.RED, 20, 0, Color.BLUE, true);
  g2d.setPaint(diagonalGradient);

  g2d.fillRect(0, 0, getWidth(), getHeight());

 }

}

Gradiente vertical cíclico

package gradientPaintDemo;

import java.awt.Color;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;

import javax.swing.JPanel;

public class VerticalCyclicGradientPanel extends JPanel {

 @Override
 public void paint(Graphics g) {
  Graphics2D g2d = (Graphics2D) g;

  /*
   * Para crear un gradiente horizontal cíclico, simplemente especificar
   * la altura del color
   * y crear el gradiente con la propiedad cíclica a "true"
   */
  GradientPaint diagonalGradient = new GradientPaint(0, 0, Color.GREEN, 0, 20, Color.YELLOW, true);
  g2d.setPaint(diagonalGradient);

  g2d.fillRect(0, 0, getWidth(), getHeight());

 }

}

Este sería el resultado de juntar todos estos ejemplos en un panel.


Para ver todo esto en funcionamiento, aquí os dejo la clase que carga la aplicación.

package gradientPaintDemo;

import java.awt.GridLayout;

import javax.swing.JFrame;
import javax.swing.JPanel;

public class GradientsDemo extends JPanel {

 private static void createAndShowGUI() {
  // Crea y prepara la ventana.
  JFrame frame = new JFrame("Ejemplos de gradientes");
  frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

  frame.getContentPane().setLayout(new GridLayout(3, 3, 10, 10));

  frame.getContentPane().add(new HorizontalGradientPanel());
  frame.getContentPane().add(new VerticalGradientPanel());
  frame.getContentPane().add(new DiagonalGradientPanel());
  frame.getContentPane().add(new RoundGradientPanel());
  frame.getContentPane().add(new HorizontalCyclicGradientPanel());
  frame.getContentPane().add(new VerticalCyclicGradientPanel());

  frame.setSize(400, 400);
  frame.setVisible(true);
 }

 public static void main(String[] args) {
  javax.swing.SwingUtilities.invokeLater(new Runnable() {
   public void run() {
    createAndShowGUI();
   }
  });

 }
}

Eso es todo por hoy, espero que lo aquí expuesto os haya sido útil de alguna manera.

Un saludo

4 comentarios:

viruspablo dijo...

Muy fácil y explicativo gracias :D

Anónimo dijo...

Muy bien explicado, gracias.

Anónimo dijo...

muy buen código

Unknown dijo...

Es lo que andaba buscando!
Muy bien explicado. Muchas Gracias.

Publicar un comentario