Can't change LineAndShapeRenderer Colours!

A discussion forum for JFreeChart (a 2D chart library for the Java platform).
Locked
cardybean
Posts: 8
Joined: Tue Dec 10, 2013 2:45 pm
antibot: No, of course not.

Can't change LineAndShapeRenderer Colours!

Post by cardybean » Sun Jan 05, 2014 12:50 pm

Hi there!

Ok so I have a project for work which aims to provide an application to display response time/call volumes for online server. I have all of the backend complete where I retrieve/format stats to feed into graphs.

I am stuck on **changing the color of the lines!*, which is strange because line colours are automatically different in this exmaple: http://www.java2s.com/Code/Java/Chart/J ... rtDemo.htm. Find the source code for my graph creation class below. Any help would be much, much appreciated (I am working on this on a Sunday as I did not want it to run into the New Year!!)

Code: Select all

package osv.onlinestatviewer;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.List;
import java.util.ArrayList;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.CategoryAxis;
import org.jfree.chart.axis.CategoryLabelPositions;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.DatasetRenderingOrder;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.renderer.category.AreaRenderer;
import org.jfree.chart.renderer.category.BarRenderer;
import org.jfree.chart.renderer.category.CategoryItemRenderer;
import org.jfree.chart.renderer.category.LineAndShapeRenderer;
import org.jfree.data.category.DefaultCategoryDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
import org.jfree.ui.ApplicationFrame;
import org.jfree.ui.RefineryUtilities;

/**
 * A simple demonstration application showing how to create a bar chart overlaid
 * with a line chart.
 */
//public class AreaLineGraph extends ApplicationFrame {
public class AreaLineGraph {

    ChartPanel chartPanel;
    CategoryPlot plot;
    CategoryPlot plot2;
    int chartIndex = 0;  
    String title;
        
    static Color colors[] = {Color.BLACK, Color.BLUE, Color.CYAN, Color.GREEN,
        Color.GRAY, Color.MAGENTA, Color.ORANGE, Color.PINK, Color.RED,
        Color.WHITE, Color.YELLOW, Color.LIGHT_GRAY };
    
    public AreaLineGraph(String t) {
        title = t;
         
        plot = new CategoryPlot();
        plot.setDomainAxis(0, new CategoryAxis("Hours"));
        plot.setRangeAxis(0, new NumberAxis("Volumes"));
        plot.setRangeAxis(1, new NumberAxis("Response Times"));
        plot.setOrientation(PlotOrientation.VERTICAL);
        plot.setRangeGridlinesVisible(true);
        plot.setDomainGridlinesVisible(true);
    }
    
    public void addDataSet(DefaultCategoryDataset ds, String type, CategoryItemRenderer r, int axisIndex)
    {
        //r.setSeriesPaint(chartIndex, colors[chartIndex]);
        
        plot.setDataset(chartIndex, ds);
        plot.setRenderer(chartIndex, r);
        plot.mapDatasetToRangeAxis(chartIndex, axisIndex);
        chartIndex++;
    }
    
    public void finalise() 
    {
        plot.setDatasetRenderingOrder(DatasetRenderingOrder.REVERSE);
        plot.getDomainAxis().setCategoryLabelPositions(CategoryLabelPositions.UP_45);
        plot.getDomainAxis().setCategoryMargin(0);
        
        for (int i = 0; i < plot.getDatasetCount(); i++) {
            plot.getRendererForDataset(plot.getDataset(i)).setSeriesPaint(0, colors[i]);
        }
        
        final JFreeChart chart = new JFreeChart(plot);
        chart.setTitle(title);
        chartPanel = new ChartPanel(chart);
        chartPanel.setPreferredSize(new java.awt.Dimension(930, 500));
        
    }
    
    public int getChartIndex()
    {
        return chartIndex;
    }
    
    public ChartPanel getChartPanel() 
    {   
        return chartPanel;
    }

}
EDIT:

Added snippets from my main class as requested. I have not included it all as there is a fair bit of unfinished code related to the rest of the application.

Code: Select all

       public static void createDailyGraph() throws FileNotFoundException {
            String type = "";
            String next = "";
            int index = 0;
            boolean start = false;
            DefaultCategoryDataset ds = new DefaultCategoryDataset();
            CategoryItemRenderer areaR = new AreaRenderer();
            CategoryItemRenderer lineR = new LineAndShapeRenderer();
            alg = new AreaLineGraph("Daily Graph Test");
            
            file = new File("C:\\Program Files\\OnlineStatViewer\\stats\\server_totals\\API059\\API059_SERVER_TOTALS_2013-12-12");
            scanner = new Scanner(file);
            
            // Creating datasets and adding them to the graph
            while (scanner.hasNext()) {
                next = scanner.next();
                if (!isNum(next)) { 
                    if(start) {
                        alg.addDataSet(ds, lineR, 1);
                        //System.out.println(type);
                        ds = new DefaultCategoryDataset();
                    }
                    else { start=true; }
                    type=next;
                    index=0;
                } else {
                    ds.addValue(Double.parseDouble(next), type, hours[index]);
                    index++;
                }          
            }
            alg.addDataSet(ds, areaR, 0); // after adding all of the other datasets I add the final one which is the total number of transactions
            alg.finalise();
            cp = alg.getChartPanel();
            displayPanel.add(cp, "CARD");
        } 
        
        
        public static boolean isNum(String str)
        {
            if(Character.isDigit(str.charAt(0))) { 
                return true;
            } return false;
        }
The data I am loading into the dataset is as below:

Code: Select all

servername 0.060 0.050 0.036 0.180 0.175 0.180 0.216 0.252 0.192 0.184 0.174 0.210 0.240 0.140 0.137 0.077 0.035
I have about 10 datasets per graph.
Last edited by cardybean on Sun Jan 05, 2014 8:04 pm, edited 1 time in total.

John Matthews
Posts: 513
Joined: Wed Sep 12, 2007 3:18 pm

Re: Can't change LineAndShapeRenderer Colours!

Post by John Matthews » Sun Jan 05, 2014 2:55 pm

Cross-posted here.

paradoxoff
Posts: 1634
Joined: Sat Feb 17, 2007 1:51 pm

Re: Can't change LineAndShapeRenderer Colours!

Post by paradoxoff » Sun Jan 05, 2014 7:02 pm

It is a bit hard to tell what is going on because some informations are missing from your snippet:
-I miss the calls the your addDataSet method. This is important because you only change the colors of the first series (or rows, as they are called for a CategoryDataset) in every dataset. If your datasets have more than one row (which is impossible to tell), the colors for the additional rows won't change.
- It is also not clear whether the "finalise" method is ever called. This is obviously necessary to get any effect.

cardybean
Posts: 8
Joined: Tue Dec 10, 2013 2:45 pm
antibot: No, of course not.

Re: Can't change LineAndShapeRenderer Colours!

Post by cardybean » Sun Jan 05, 2014 8:08 pm

Hi Paradoxoff and thanks for your response.

I have edited my initial post to include a snippet from my main class which shows the method creating the graph as well as another isNum method I call.

I figured out why the example code I quoted was outputting lines with different colours - because each line (only 2) had its own axis. I however, with my 10 LineAndShapeRenderers cannot do this (I did however try).

I have taken a look at this whole series thing, and tbh it confused me. There are some parts of this API which baffle me. If you could give me a pointer or an example of how I can do this with my current setup that would be great. I am getting very frustrated at this very little thing.

The beauty however is once I have this method of creating this graph working (which it does aside from the line colours) I can proceed with the rest of my application like a breeze!

Thanks again- and as this if fairly urgent I wouldn't mind if you send me a wee email on sacbnc @ gmail.com.

david.gilbert
JFreeChart Project Leader
Posts: 11734
Joined: Fri Mar 14, 2003 10:29 am
antibot: No, of course not.
Contact:

Re: Can't change LineAndShapeRenderer Colours!

Post by david.gilbert » Mon Jan 06, 2014 11:28 am

Your code is messy so I won't pretend I understand all of it, but it looks like you are creating only one line renderer and using it for all the datasets. So if you change the color of series 0 for the renderer, that will affect series 0 in all the datasets.
David Gilbert
JFreeChart Project Leader

:idea: Read my blog
:idea: Support JFree via the Github sponsorship program

cardybean
Posts: 8
Joined: Tue Dec 10, 2013 2:45 pm
antibot: No, of course not.

Re: Can't change LineAndShapeRenderer Colours!

Post by cardybean » Mon Jan 06, 2014 11:39 am

Thanks for the reply and patience with my messy code david.gilbert.

So I need a series for each dataset? When I have looked into this it looks as though I create a series as opposed to a dataset. Could you possibly give a small example in-line with my current creation of datasets explaining this?

paradoxoff
Posts: 1634
Joined: Sat Feb 17, 2007 1:51 pm

Re: Can't change LineAndShapeRenderer Colours!

Post by paradoxoff » Mon Jan 06, 2014 3:23 pm

I am currently reminded of my first steps with JFreeChart :-). In fact, the JFreeChart concepts of datasets, series/rows, renderers, and axes is quite straightforward.
- A plot can have multiple datasets. The dataset is added via plot.setDataset(int datasetIndex, CategoryDataset dataset)
- Each dataset should have its own renderer. The renderer is added via plot.setRenderer(int datasetIndex, CategoryItemRenderer renderer );
- A dataset can have multiple rows. The color of each row is defined via renderer.setSeriesPaint(int seriesIndex, Paint thePaint);
- Each dataset can be mapped to a separate x and/or y axis.
cardybean wrote: So I need a series for each dataset? When I have looked into this it looks as though I create a series as opposed to a dataset.
You cannot create series or rows separately. You can only create datasets, and the adding values to them (dataset,addValue(double value, Comparable rowKey, Comparable columnKey)). Each unique row key corresponds to a separate entry in the legend, and allows to define an individual series paint.
cardybean wrote:I figured out why the example code I quoted was outputting lines with different colours - because each line (only 2) had its own axis. I however, with my 10 LineAndShapeRenderers cannot do this (I did however try).
I would rather say the reason for the different colors is that each line (where "line" could probably replaced with "dataset") had its own renderer.

Further comments on your code are still hard because the snippet is still not runnable or even complete. There is still no main method, and the used variable hours (that is used to create the columnKeys) is never referenced. All I can tell is that it is an array of Comparables.

david.gilbert
JFreeChart Project Leader
Posts: 11734
Joined: Fri Mar 14, 2003 10:29 am
antibot: No, of course not.
Contact:

Re: Can't change LineAndShapeRenderer Colours!

Post by david.gilbert » Mon Jan 06, 2014 3:38 pm

A CategoryDataset is just a (two-dimensional) table of values with rows and columns. The values in one row are considered a "series", and there is column for each category:

Code: Select all

         | Category A | Category B
---------+------------+-----------
Series 1 |        1.0 |        3.0
Series 2 |        2.0 |       null
So in the dataset above the first series has rowKey = "Series 1" and contains the value 1.0 for Category A and 3.0 for Category B. As Paradoxoff has explained, you don't create a series---you just add data values and rows (series) are added to the dataset as required. Note that null entries will exist for any cells in the table that you don't set the value for.

At one point, I was going to generalize the renderer code so that it could treat either rows OR columns as series, which would make it trivial to transpose a dataset. I still think that is a good idea, but the benefit is small compared to the amount of code that would need to be changed.
David Gilbert
JFreeChart Project Leader

:idea: Read my blog
:idea: Support JFree via the Github sponsorship program

cardybean
Posts: 8
Joined: Tue Dec 10, 2013 2:45 pm
antibot: No, of course not.

Re: Can't change LineAndShapeRenderer Colours!

Post by cardybean » Tue Jan 07, 2014 8:30 am

Hi guys, thanks a lot for all you responses. Will making me more informed of JFreeChart I have also solved the issue - it was because I only had one renderer. I had overlooked this and for some reason thought I had changed it from

Code: Select all

alg.addDataSet(ds, areaR, 0);
to

Code: Select all

alg.addDataSet(ds, new AreaRenderer(), 0);
and thus thought the former didn't work. But this turned out to be one those problems you get while programming, that are nothing but idiotic!

Also, great lib Dave.

Locked