如何使使用“ jfreecharts”进行的绘图更加动态?

时间:2019-01-03 22:48:43

标签: java dynamic jfreechart

简介

我的目标是输入一组产品并选择显示选项,例如:

System.out.print("Input number of products to represent: ");
      prodNum = scan.nextInt();
      String[] prodName = new String[prodNum];
System.out.print("Enter which products to represent: ");
     for (int i = 0; i < prodName.length; i++)
         {
           prodName[i] = scan.next();
         }
System.out.println("----Options----");
System.out.println("1. Cantidad");
System.out.println("2. Calidad");
System.out.println("3. RealmQ");
System.out.println("4. Coste");
      option = scan.nextInt();                

      userOptionWas(option);

然后通过使用JFreeCharts,我希望能够选择存储在一些明显命名的数组中的行数(对于我输入的每种产品)以及要显示的选项(数量,质量和填充物)。

我的方法

  private XYDataset multipleLine(int prodNum, String[] prodName, int option){

   XYSeriesCollection dataset = new XYSeriesCollection();

   XYSeries product3 = new XYSeries("product3");
   XYSeries product4 = new XYSeries("product4");
   XYSeries product5 = new XYSeries("product5");
   XYSeries product6 = new XYSeries("product6");
   XYSeries product7 = new XYSeries("product7");
   XYSeries product8 = new XYSeries("product8");

   switch(prodNum)
   {
       case(2):
       {

           if (option == 1)
           {
                XYSeries product1 = new XYSeries(prodName[0]);
                XYSeries product2 = new XYSeries(prodName[1]);

                for (int i = 0; i < CSVinput.cantidad.length; i++)
                {
                    try
                    {
                        if (CSVinput.nombre[i].equals(prodName[0]))
                        {                            
                            product1.add(i, CSVinput.cantidad[i]);
                        }
                    }catch(ArrayIndexOutOfBoundsException e){}
                    }
           }
           if (option == 2)
           {

           }
           if (option == 3)
           {

           }
           if (option == 4)
           {

           }

       }
   }       
   return dataset;
 }

在实现我的想法的一半过程中,我开始怀疑是否有可能做到这一点,或者只是我走错了方向。

我期望的结果

  • 我希望能够从之前显示的简单菜单中创建不同的图。
  • 如果可能,是动态的(如果我输入2种产品,程序将显示2行引用每个产品

附加说明

  • 我是JFreeCharts的新手。

  • product1.add(i, CSVinput.cantidad[i]);上花点时间,在这里我使用(int)“ i”代替我的(String)“ date”格式。为什么我不能使用字符串?有什么办法可以绕过这个?

我对这个问题的期望

我想知道更高效,更友好的方式来实现这一目标,而又不会带来太多不必要的复杂性。

数据示例

2018/12/29-Tejido,321 908,13.55,43.18,$15.98,
2018/12/29-Ropa,195 045,20.55,45.93,$123.01,
2018/12/29-Gorra de visera,126 561,17.43,42.32,$79.54,
2018/12/29-Cerveza,80 109,3.37,17.93,$12.38,
2018/12/29-Mercancías de playa,75 065,11.48,39.73,$105.93,
2018/12/29-Bebidas alcohólicas,31 215,4.84,27.90,$32.29,
2018/12/29-Artículos de cuero,19 098,23.13,44.09,$198.74,
2018/12/29-Bolsas y carteras,7 754,23.09,41.34,$1 176.54,
2018/12/30-Tejido,252 229,12.86,43.14,$18.87,
2018/12/30-Ropa,132 392,18.09,46.02,$177.58,
2018/12/30-Gorra de visera,87 676,14.42,42.46,$122.48,
2018/12/30-Cerveza,44 593,2.72,17.79,$18.71,
2018/12/30-Mercancías de playa,44 593,8.26,39.56,$200.78,
2018/12/30-Bebidas alcohólicas,27 306,4.30,23.88,$31.95,
2018/12/30-Artículos de cuero,16 147,21.08,43.91,$207.49,
2018/12/30-Bolsas y carteras,6 552,21.11,40.59,$1 195.41,
2019/01/02-Tejido,321 908,13.55,43.18,$15.98,
2019/01/02-Ropa,195 045,20.55,45.93,$123.01,
2019/01/02-Gorra de visera,126 561,17.43,42.32,$79.54,
2019/01/02-Cerveza,80 109,3.37,17.93,$12.38,
2019/01/02-Mercancías de playa,75 065,11.48,39.73,$105.93,
2019/01/02-Bebidas alcohólicas,31 215,4.84,27.90,$32.29,
2019/01/02-Artículos de cuero,19 098,23.13,44.09,$198.74,
2019/01/02-Bolsas y carteras,7 754,23.09,41.34,$1 176.54,
2019/01/03-Tejido,1 164 607,12.87,43.14,$15.54,
2019/01/03-Ropa,131 409,17.18,45.97,$161.17,
2019/01/03-Gorra de visera,79 242,13.54,43.17,$100.38,
2019/01/03-Cerveza,48 332,2.80,18.10,$17.48,
2019/01/03-Mercancías de playa,46 157,8.70,38.39,$180.54,
2019/01/03-Bebidas alcohólicas,25 210,4.04,23.72,$33.52,
2019/01/03-Artículos de cuero,14 321,19.56,39.92,$216.00,
2019/01/03-Bolsas y carteras,5 814,19.85,39.68,$1 227.29,

编辑:

非常感谢我想我学到的帮助,但是由于某些原因,该方法永远不会结束,采用数据集的实例不会绘制数据集 我缺少什么?

PD:在评论中让我知道是否需要CSV输入以提供解决方案。

import java.awt.Color;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.time.ZonedDateTime;
import java.util.Date;
import java.util.Scanner;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.XYPlot;
import org.jfree.data.general.SeriesException;
import org.jfree.data.time.Day;
import org.jfree.data.time.Second;
import org.jfree.data.time.TimeSeries;
import org.jfree.data.time.TimeSeriesCollection;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
import org.jfree.ui.ApplicationFrame;
import org.jfree.ui.RefineryUtilities;

import webscrapper.CSVinput;

/**
 *
 * @author Jonathan
 */
public class TimeSeriesChartExample extends ApplicationFrame{

    //To parse dates below and be able to debug outside the loop
    public static String[] dateSplit;

    //Instace that declares properties and uses the dataset to create the chart
    public TimeSeriesChartExample(String title) 
    {
       super(title);
       // Create dataset
       XYDataset dataset = createDataset();
       // Create chart
       JFreeChart chart = ChartFactory.createTimeSeriesChart(
           "Titulo", // Chart
           "Date", // X-Axis Label
           "Number", // Y-Axis Label
           dataset);

        //Changes background color
        XYPlot plot = (XYPlot)chart.getPlot();
        plot.setBackgroundPaint(new Color(255,228,196));  
    }
    //Create the set of data to be plotted
    private XYDataset createDataset() 
    {
        //A collection of datasets
        TimeSeriesCollection dataset = new TimeSeriesCollection();
        //The object were this new series are added thus it's name
        TimeSeries prod1 = new TimeSeries("Cantidad");

            //"For each" name stored in the array
            for (int i = 0; i < CSVinput.nombre.length; i++)
            {
                //If name equals 
                if ("Ropa".equals(CSVinput.nombre[i]))
                {
                    //Pass the "i" position to work it
                    dateSplit = CSVinput.fecha[i].split("/");
                        //Parse the date
                        int day = Integer.parseInt(dateSplit[2]);
                        int month = Integer.parseInt(dateSplit[1]);
                        int year = Integer.parseInt(dateSplit[0]);
                        System.out.println("day is: " + day);
                    //Pass the parsed date and the value from CSV.cantidad at "i" position referring to the name "Ropa"
                    prod1.add(new Day(day, month, year), CSVinput.cantidad[i]);
                    System.out.println(CSVinput.cantidad[i]);//Debug stuff
                }         
            }                    
            //Add everything to the dataset
            dataset.addSeries(prod1);     
        //Return it
        return dataset;
    }
    private XYDataset createDataset2()
    {
        //A collection of datasets
        TimeSeriesCollection dataset = new TimeSeriesCollection();
        //The object were this new series are added thus it's name
        TimeSeries prod2 = new TimeSeries("Cantidad");

            //"For each" name stored in the array
            for (int i = 0; i < CSVinput.nombre.length; i++)
            {
                //If name equals 
                if (CSVinput.nombre[i] == "Tejido")
                {
                    //Pass the "i" position to work it
                    dateSplit = CSVinput.fecha[i].split("/");
                        //Parse the date
                        int day = Integer.parseInt(dateSplit[0]);
                        int month = Integer.parseInt(dateSplit[1]);
                        int year = Integer.parseInt(dateSplit[2]);
                    //Pass the parsed date and the value from CSV.cantidad at "i" position referring to the name "Ropa"
                    prod2.add(new Day(day, month, year), CSVinput.cantidad[i]);
                    System.out.println(CSVinput.cantidad[i]);//Debug stuff
                }         
            }                    
            //Add everything to the dataset
            dataset.addSeries(prod2);     
        //Return it
        return dataset;
    }

    public static void main(String[] args) throws FileNotFoundException
    {       
       //Custom class to import data from the csv into arrays (TODO: make it dynamic)
       CSVinput.ImportData("caca.csv");

       /* //More debugg stuff
       dateSplit = CSVinput.fecha[1].split("/");
       System.out.println("year: " + dateSplit[0] + " month: " + dateSplit[1] + " day: " + dateSplit[2]);
       */

       //Create an instance of the previous class 
       final TimeSeriesChartExample example = new TimeSeriesChartExample("ItWorks!");
       example.pack(); //Part from the ApplicationFrame
       RefineryUtilities.centerFrameOnScreen(example); //Render the graph at the center of screen
       example.setVisible(true);  //make it visible
    }
    }

1 个答案:

答案 0 :(得分:1)

首先,关注程序的数据模型:

  • 如果您的系列包含时域,请考虑使用TimeSeriesCollection中的TimeSeries而不是XYSeriesTimeSeriesChartDemo1(引用here)是一个基本示例;解析日期,如herehere所示;对于数据库访问,请考虑使用JDBCXYDataset

  • 在读取每个系列的数据时,将系列存储在List<TimeSeries>中,而不是数组中;如果延迟是一个问题,请在后台进行解析,如here所示。

确切的细节将取决于您的应用程序的设计,但是使用observer pattern将使复杂性降到最低;基本原理是更新模型Dataset),而监听的 view JFreeChart)也会进行更新。例如,使用Swing,您可以通过多种方式控制显示的图表:

  • 使用您的List<TimeSeries>来构建合适的ListModel<TimeSeries>;对于系列菜单,将所选模型设为DefaultComboBoxModel<TimeSeries>的{​​{1}}或JComboBox的{​​{1}}。

  • 向菜单组件添加合适的侦听器;给您的DefaultListModel<TimeSeries>一个JList;使用XYPlotTimeSeriesCollection可以在选择序列时更改绘图;或者,使用addSeries()切换可见性,如图here所示。

对于命令行界面,交互不那么复杂,但用途也较少:

  • 使用removeSeries()来构建setSeriesVisible()

  • 使用List<TimeSeries>方法来控制正在监听的TimeSeriesCollection显示的内容。