Una forma sencilla y rápida de aprender JAVA, observando y deduciendo cómo se comporta el lenguaje a través de ejemplos prácticos.

jueves, 23 de octubre de 2014

Gráficas con JFreeChart (VIII). Ejemplo práctico basado en la Teoría del Caos.

Este ejemplo nos proponemos a demostrar gráficamente la rica conducta caótica de una ecuación demográfica interada.
Para ello necesitamos que la gráfica se vaya actualizando automáticamente a medida que vayamos modificando los distintos valores de entrada de la ecuación.

Empezamos por crear un nuevo proyecto de tipo JFrame y en modo de diseño le agregamos un jPanel para mostrar la gráfica. También añadimos 4 jSpinner con sus correspondientes jLabels y un jButton para restablecer las entradas a valores predeterminados.
Debería quedar algo parecido a eso:




Código:

package freejchartpanel1;

import javax.swing.JOptionPane;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;

public class Ventana1 extends javax.swing.JFrame {

    public double k;
    public double poblacion;
    public double tasaNatalidad;
    public int generaciones;

    public Ventana1() {
        initComponents();
        restablecer();
        actualizar();
    }

    
    private void initComponents() { ... }// Aquí va código generado por Netbeans

    private void jSpinnerPoblacionInicialStateChanged(javax.swing.event.ChangeEvent evt) {                                                     
        actualizar();
        ejecutar();
    }

    private void jSpinnerCapacidadCargaStateChanged(javax.swing.event.ChangeEvent evt) {                                                   
        actualizar();
        ejecutar();
    } 

    private void jSpinnerNatalidadStateChanged(javax.swing.event.ChangeEvent evt) {                                              
        actualizar();
        ejecutar();
    }                                              

    private void jSpinnerGeneracionesStateChanged(javax.swing.event.ChangeEvent evt) {                                                 
        actualizar();
        ejecutar();
    }                                                 

    private void jButtonRestablecerActionPerformed(java.awt.event.ActionEvent evt) {                                                  
        restablecer();
    }                                                  

    public static void main(String args[]) {

        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new Ventana1().setVisible(true);
            }
        });
    }

    // Variables declaration - do not modify                     
    private javax.swing.JButton jButtonRestablecer;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel jLabel4;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JPanel jPanel2;
    private javax.swing.JSpinner jSpinnerCapacidadCarga;
    private javax.swing.JSpinner jSpinnerGeneraciones;
    private javax.swing.JSpinner jSpinnerNatalidad;
    private javax.swing.JSpinner jSpinnerPoblacionInicial;
    // End of variables declaration                   

    private void actualizar() {

        k = Double.parseDouble(jSpinnerCapacidadCarga.getValue().toString());
        poblacion = Double.parseDouble(jSpinnerPoblacionInicial.getValue().toString());
        tasaNatalidad = Double.parseDouble(jSpinnerNatalidad.getValue().toString()) / 100;
        generaciones = Integer.parseInt(jSpinnerGeneraciones.getValue().toString());

        // Control rango maximos minimos jSpinners
        if (k <= 1) {
            jSpinnerCapacidadCarga.setValue(1);
        } else if (poblacion >= k) {
            jSpinnerPoblacionInicial.setValue(k);
        } else if (poblacion <= 1) {
            jSpinnerPoblacionInicial.setValue(1);
        } else if (tasaNatalidad <= 0) {
            jSpinnerNatalidad.setValue(0);
        } else if (generaciones <= 0) {
            jSpinnerGeneraciones.setValue(0);
        }

    }

    private void restablecer() {

        jSpinnerCapacidadCarga.setValue(10000);
        jSpinnerPoblacionInicial.setValue(7000);
        jSpinnerNatalidad.setValue(120); // %
        jSpinnerGeneraciones.setValue(30);

    }

    private void ejecutar() {

        int extincion = 0;

        XYSeries series = new XYSeries("");

        for (int i = 0; i < generaciones; i++) {
            series.add(i, poblacion);
            poblacion = (poblacion * tasaNatalidad * (k - poblacion)) / k;
            if (poblacion <= 0) {
                extincion = i + 1;
                series.add(i + 1, 0);
                break;
            }
        }

        XYSeriesCollection dataset = new XYSeriesCollection();
        dataset.addSeries(series);

        JFreeChart chart = ChartFactory.createXYLineChart(
                "Índice Demográfico",
                "Generación ->",
                "Población ->",
                dataset,
                PlotOrientation.VERTICAL,
                false,
                false,
                false
        );

        // Mostramos la grafica dentro del jPanel1
        ChartPanel panel = new ChartPanel(chart);
        jPanel1.removeAll();
        jPanel1.setLayout(new java.awt.BorderLayout());
        jPanel1.add(panel);
        jPanel1.validate();

        if (extincion != 0) {
            JOptionPane.showMessageDialog(null, "Extinción en la Generación " + (extincion));
        }

    }

}


Resultado:



martes, 21 de octubre de 2014

Gráficas con JFreeChart (VII). Poner un rango fijo en el Eje X.

Esta vez nos interesa poner el eje X de la gráfica a una escala fija (no auto-escalable). Antes cuando se creaba una gráfica el eje X se adaptaba automáticamente a los valores máximos y mínimos recibidos. Ahora queremos que el rango del eje X esté entre 0 y 100 (independientemente de los valores recibidos).

Para poder apreciar bien la diferencia he usado como plantilla el ejemplo del post "Gráficas con JFreeChart (V)" cuyo Eje X se adaptaba al valor máximo recibido que era 60. En este caso el Eje X de la gráfica se adapatará al rango que le hayamos indicado (0-100).


Código (Demografia.java):

package crecimientoPoblacion;

import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartFrame;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.data.category.DefaultCategoryDataset;


public class Demografia1 {

    public static void main(String[] args) {

        DefaultCategoryDataset dataset = new DefaultCategoryDataset();

        double poblacion = 25;
        int esperanza_de_vida = 5;
        double defunciones;
        double poblacion_neta;

        double tc = 0.2; // tasa de crecimiento 20%
        double tm = 0.4; // tasa de mortalitat 40%

        for (int tiempo = 0; tiempo < esperanza_de_vida; tiempo++) {

            // Crecimiento
            poblacion = poblacion * (1 + tc);
            dataset.addValue(poblacion, "Crecimiento", "" + tiempo);

            // Mortalidad
            defunciones = poblacion * tm;
            dataset.addValue(defunciones, "Mortalidad", "" + tiempo);

            // Crecimiento Neto
            poblacion_neta = (poblacion - defunciones);
            dataset.addValue(poblacion_neta, "Crecimiento neto", "" + tiempo);

        }

        JFreeChart chart = ChartFactory.createLineChart(
                "Calculo demografico",
                "Tiempo",
                "Población",
                dataset,
                PlotOrientation.VERTICAL,
                true,
                false,
                false
        );
        
        // Rango Eje X estático de 0 a 100
        CategoryPlot plot = chart.getCategoryPlot();
        NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis();
        rangeAxis.setRange(0, 100);    
        
        // Mostramos la grafica en pantalla
        ChartFrame fr = new ChartFrame("Cálculo Demográfico II", chart);
        fr.pack();
        fr.setVisible(true);

    }

}


Resultado:





















Gráficas con JFreeChart (VI). Poner la gráfica dentro un jPanel.

Creamos un nuevo proyecto de tipo "JFrame Form" y en modo diseño le agregamos un jPanel y un jButton.





Código (Ventana1.java):

package freejchartpanel1;

import javax.swing.JFrame;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;


public class Ventana1 extends javax.swing.JFrame {
   
    public Ventana1() {
        initComponents();        
    }
                         
    private void initComponents() {...} // aqui va el codigo generado automáticamente por NetBeans

    private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {

        double poblacion = 0.7;
        double tasa_crecimiento = 3.9;

        XYSeries series = new XYSeries("");

        for (int i = 0; i < 30; i++) {

            series.add(i, poblacion * 100);
            // Variante de la ecuacion de Verhulst
            poblacion = poblacion * tasa_crecimiento * (1 - poblacion);
        }

        XYSeriesCollection dataset = new XYSeriesCollection();
        dataset.addSeries(series);

        JFreeChart chart = ChartFactory.createXYLineChart(
                "Crecimiento Población",
                "Tiempo ->",
                "Población ->",
                dataset,
                PlotOrientation.VERTICAL,
                false,
                false,
                false
        );

        // Mostramos la grafica dentro del jPanel1
        ChartPanel panel = new ChartPanel(chart);        
        jPanel1.setLayout(new java.awt.BorderLayout());
        jPanel1.add(panel);   
        jPanel1.validate();

    }                                        

    public static void main(String args[]) {
        /* Create and display the form */
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new Ventana1().setVisible(true);
            }
        });
    }

    // Variables declaration - do not modify                     
    private javax.swing.JButton jButton1;
    private javax.swing.JPanel jPanel1;
    // End of variables declaration                   
}


Resultado:




















martes, 14 de octubre de 2014

Gráficas con JFreeChart (V). Multi-Lineas en una sola gráfica.

El siguiente ejemplo práctico trata de mostrarnos varios datos en una misma gráfica, representado por varias lineas temporales. Para ilustrar tal efecto he elegido la representación de la tasa de crecimiento poblacional de algún insecto o animal, con sus respectivas variantes de mortalidad y crecimiento neto.


Código:

package crecimientoPoblacion;

import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartFrame;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.data.category.DefaultCategoryDataset;

public class Demografia1 {

    public static void main(String[] args) {

        DefaultCategoryDataset dataset = new DefaultCategoryDataset();

        double poblacion = 25;
        int esperanza_de_vida = 5;
        double defunciones;
        double poblacion_neta;

        double tc = 0.2; // tasa de crecimiento 20%
        double tm = 0.4; // tasa de mortalidad 40%

        for (int tiempo = 0; tiempo < esperanza_de_vida; tiempo++) {

            //Crecimiento
            poblacion = poblacion * (1 + tc);
            dataset.addValue(poblacion, "Crecimiento", "" + tiempo);

            //Mortalidad
            defunciones = poblacion * tm;
            dataset.addValue(defunciones, "Mortalidad", "" + tiempo);

            //Crecimiento Neto
            poblacion_neta = poblacion - defunciones;
            dataset.addValue(poblacion_neta, "Crecimiento neto", "" + tiempo);

        }

        JFreeChart chart = ChartFactory.createLineChart(
                "Calculo demografico",
                "Tiempo",
                "Población",
                dataset,
                PlotOrientation.VERTICAL,
                true,
                false,
                false
        );

        //Mostramos la grafica en pantalla
        ChartFrame fr = new ChartFrame("Calculo Demografico I", chart);
        fr.pack();
        fr.setVisible(true);

    }

}


Resultado:





















jueves, 2 de octubre de 2014

Empaquetar aplicación y sus librerías en un solo archivo ".jar" con NetBeans

Cuando empaquetamos nuestras aplicaciones jFreeChart con NetBeans (pulsando "Clean and Build") se genera un archivo ".jar" y una carpeta "lib" que contiene las librerías del jFreeChart.

...\NetBeansProjects\Aplicacion2\dist\Aplicacion1.jar
...\NetBeansProjects\Aplicacion2\dist\lib\jcommon-1.0.23.jar
...\NetBeansProjects\Aplicacion2\dist\lib\jfreechart-1.0.19.jar

Si queremos que estas librerías se empaqueten también y se genere todo el proyecto en un solo archivo ".jar",debemos modificar el archivo "build.xml" que podemos encontrar en la raiz del proyecto.

...\NetBeansProjects\Aplicacion2\build.xml


Editamos este archivo agregando el siguiente código antes del tag de cierre "</project>":


Código (build.xml):

...

  <target name="package-for-store" depends="jar">  
     <property name="store.jar.name" value="Aplicacion2"/>  
     <property name="store.dir" value="store"/>  
     <property name="store.jar" value="${store.dir}/${store.jar.name}.jar"/>  
     <echo message="Packaging ${application.title} into a single JAR at ${store.jar}"/>  
     <delete dir="${store.dir}"/>  
     <mkdir dir="${store.dir}"/>  
     <jar destfile="${store.dir}/temp_final.jar" filesetmanifest="skip">  
       <zipgroupfileset dir="dist" includes="*.jar"/>  
       <zipgroupfileset dir="dist/lib" includes="*.jar"/>  
       <manifest>  
         <attribute name="Main-Class" value="${main.class}"/>  
       </manifest>  
     </jar>  
     <zip destfile="${store.jar}">  
       <zipfileset src="${store.dir}/temp_final.jar"  
       excludes="META-INF/*.SF, META-INF/*.DSA, META-INF/*.RSA"/>  
     </zip>  
     <delete file="${store.dir}/temp_final.jar"/>  
  </target>  

</project>


Una vez modificado y guardado le damos al "Clean and Build" desde NetBeans (proceso que tarda unos 50 segundos). 
Luego en la pestaña de "Files" de NetBeans, le damos clic derecho sobre "build.xml" y en el menú que aparece seguimos la siguiente ruta:

Run Target -> Other Targets -> package_for_store (dandole clic a este último).


Finalmente ya tenemos el ".jar" y las librerías jFreeChart empaquetadas en un solo archivo ".jar" en la carpeta "store" de nuestro proyecto:

...\NetBeansProjects\Aplicacion2\store\Aplicacion2.jar


Con la tecnología de Blogger.