Different colours on a line between 2 data points

A discussion forum for JFreeChart (a 2D chart library for the Java platform).
chiewboon
Posts: 3
Joined: Thu Jan 04, 2007 5:13 am

Different colours on a line between 2 data points

Post by chiewboon » Thu Jan 04, 2007 5:19 am

Hi,

I'm plotting a line graph for monitoring temperature and wish to have the line colored with red if it's above say 37.5 (C) and green if below.


For example I have a item 36 (C) and next item 38 (C).
So in my graph, I will only need to highlight the portion of the line above 37.5 (C) as red and not the whole line.

Please advise if it is possible.

Thank you.

matinh
Posts: 483
Joined: Fri Aug 11, 2006 10:08 am
Location: Austria

Post by matinh » Thu Jan 04, 2007 12:48 pm

As far as I know JFreeChart does not support this at the moment. However it shoudn't be too hard to implement it yourself. Just derive a new renderer class from whatever renderer you are using (possibly XYLineAndShapeRenderer) and reimplement the draw() method to do what you want.

hth,
- martin

jfreeuser2006
Posts: 59
Joined: Mon Nov 20, 2006 1:00 pm

Post by jfreeuser2006 » Mon Jan 08, 2007 2:24 am

you could do something like this:

Code: Select all

plot.setRenderer(new LineAndShapeRenderer() {
    public Paint getItemPaint(int row, int item) {
        double temp = plot.getDataset().getValue(row, item).doubleValue();

        if (temp >= limit) {
            return Color.RED;
        }

        return Color.BLUE;
    }

    public Shape getItemShape(int row, int item) {
        return ShapeUtilities.createDiamond(2.0f);
    }
});

willi.firulais
Posts: 15
Joined: Fri Jul 28, 2006 4:31 pm

Access to plot?

Post by willi.firulais » Thu Feb 08, 2007 10:51 pm

How to get access to the plot when using a XYLineAndShapeRenderer?

Code: Select all

plot.setRenderer(new XYLineAndShapeRenderer() {
        ...
         double temp = getPlot().getDataset().getYValue(row, item);
        ...
Thx, Willi

RichardWest
Posts: 844
Joined: Fri Oct 13, 2006 9:29 pm
Location: Sunnyvale, CA

Re: Access to plot?

Post by RichardWest » Fri Feb 09, 2007 1:00 am

willi.firulais wrote:How to get access to the plot when using a XYLineAndShapeRenderer?
One of the joys of Java (or curses, take your pick). Since the XYLineAndShapeRenderer is being declared with a new getItemPaint(), it becomes an "inner class" which means it can access variables that are declared in the outside class or the function. I use this trick a lot when defining buttons. It is a pain to make everything you want to modify with the button either global or accessable via a getter function. Abusing is feature is easy, but it has caused me much pain when it goes wrong.

Hope that helps explain what is going on. jfreeuser2006's solution is rather good by eye -- I haven't tested it, so I cannot be 100% sure.
Richard West
Design Engineer II
Advanced Micro Devices
Sunnyvale, CA

jfreeuser2006
Posts: 59
Joined: Mon Nov 20, 2006 1:00 pm

Post by jfreeuser2006 » Fri Feb 09, 2007 1:41 am

jfreeuser2006 wrote:
plot.setRenderer(new LineAndShapeRenderer() {
public Paint getItemPaint(int row, int item) {
double temp = plot.getDataset().getValue(row, item).doubleValue();

if (temp >= limit) {
return Color.RED;
}

return Color.BLUE;
}

public Shape getItemShape(int row, int item) {
return ShapeUtilities.createDiamond(2.0f);
}
});

I used this in a CategoryPlot.

For the XYLineAndShapeRenderer I think this is used in tandem with an XYPlot. Correct me if I'm wrong, I haven't actually used the XYPlot for my charts yet.

And yes it becomes an innerclass... so to access variables from the outer class, variables have to be declared final to access them within the inner class..

RichardWest
Posts: 844
Joined: Fri Oct 13, 2006 9:29 pm
Location: Sunnyvale, CA

Post by RichardWest » Fri Feb 09, 2007 1:55 am

jfreeuser2006 wrote:For the XYLineAndShapeRenderer I think this is used in tandem with an XYPlot.
Yes, XYLineAndShareRenderer is used with XYPlot.
jfreeuser2006 wrote:And yes it becomes an innerclass... so to access variables from the outer class, variables have to be declared final to access them within the inner class..
I forgot to add that detail. Thanks jfreeuser2006.
Richard West
Design Engineer II
Advanced Micro Devices
Sunnyvale, CA

jfreeuser2006
Posts: 59
Joined: Mon Nov 20, 2006 1:00 pm

Post by jfreeuser2006 » Sun Feb 11, 2007 5:44 am

Hi Richard,

I was wondering if you ran into formatting of subtitles for the charts.

Currently the TextTitle ignores \t and \u0009. It just treats these escape codes as single white spaces. Have you tried formatting the TextTitles? If yes, could you show me how? Thanks :-)

RichardWest
Posts: 844
Joined: Fri Oct 13, 2006 9:29 pm
Location: Sunnyvale, CA

Post by RichardWest » Sun Feb 11, 2007 9:17 am

jfreeuser2006 wrote:Currently the TextTitle ignores \t and \u0009. It just treats these escape codes as single white spaces. Have you tried formatting the TextTitles?
I have seen this posted several times in the forum, but I do not have an answer for this. I have never had a need to worry about this in my application, but I think there are solutions posted in other threads. I don't have the time to look right now, but if you find one, attach the url in a reply. I shall do the same if I stumble across one.

Sorry I couldn't help,
Richard West
Design Engineer II
Advanced Micro Devices
Sunnyvale, CA

jfreeuser2006
Posts: 59
Joined: Mon Nov 20, 2006 1:00 pm

Post by jfreeuser2006 » Thu Feb 15, 2007 6:50 am

Hi Richard,

I still haven't gotten around the tabbing for the TextTitle.

Anybody have a code to subclass the TextTitle so that it accepts the \u and \u0009 escape codes for tab stops?

Would be great if someone would post it.

Thanks :-)

RichardWest
Posts: 844
Joined: Fri Oct 13, 2006 9:29 pm
Location: Sunnyvale, CA

Post by RichardWest » Thu Feb 15, 2007 9:16 am

jfreeuser2006 wrote:Anybody have a code to subclass the TextTitle so that it accepts the \u and \u0009 escape codes for tab stops?
I am afraid I don't have the time to work on a solution. If I had a need that necessitate figuring one out, I would. The only threads I can find are those you have already commented on.

http://www.jfree.org/phpBB2/viewtopic.php?t=20239
http://www.jfree.org/phpBB2/viewtopic.php?t=20162
http://www.jfree.org/phpBB2/viewtopic.php?t=18462
http://www.jfree.org/phpBB2/viewtopic.php?t=399

My suggestion is for you to follow David's advice and implement a solution based upon it. It would probably be quicker for you to hack up a solution that meets your own needs than to wait for someone to provide a solution you need to adapt. It will take even more time before some one writes a solution general enough that David can incorporate it into JFreeChart.

Your solution doesn't have to be elegant; it just has to meet your needs. Why not split the String at the "\t" character and compute the extra whitespace padding (ie spaces) you need to tab it out. For instance, if you want to have an 8-space tab:

Code: Select all

Old String = "Happy\tTabs"
 * Split the string on '\t' into "Happy" and "Tabs"
 * "Happy" is 5 characters long, so we need 3 extra spaces
New String = "Happy" + "   " + "Tabs" = "Happy   Tabs"

Old String = "Happy\tTabs\tTwice"
 * Split the string on '\t' into "Happy" and "Tabs" and "Twice"
 * "Happy" is 5 characters long, so we need 3 extra spaces between "Happy" and "Tabs"
 * "Tabs" is 4 characters long, so we need 4 extra spaces between "Tabs" and "Twice"
New String = "Happy" + "   " + "Tabs" + "    " + "Twice" = "Happy   Tabs   Twice"
While this is just psuedocode, it should not take too much effort to translate it into real Java code. Hope this helps,
Richard West
Design Engineer II
Advanced Micro Devices
Sunnyvale, CA

jfreeuser2006
Posts: 59
Joined: Mon Nov 20, 2006 1:00 pm

Post by jfreeuser2006 » Thu Feb 22, 2007 7:40 am

Hi Richard,

I'm posting the code i made for parsing tabs. For my code i used
the \u0009 for my tabs.

i hope it can be useful to somebody.

Code: Select all

public String parseTab(String str) {
        String[] token = str.split("\\u0009");
        int len = 0;
        String newStr = "";
        String temp = "";
        String space = " ";
        
        for(int i = 0; i < token.length; i++) {
            if (token[i].length() < 8) {
                len = 8 - token[i].length();
                for (int j = 0; j < len; j++){
                    temp = temp + space;
                }
                if (i != 0) {
                    temp = temp + token[i];
                }
                else {
                    temp = token[i];
                }
            }
            
            newStr = newStr + temp;
            
            temp = "";
        }

        return newStr;
}

Please do comment on my code. I'd appreciate any suggestions.

Regards,
Jaypee

tvarsa
Posts: 1
Joined: Thu Feb 22, 2007 3:15 pm

Post by tvarsa » Thu Feb 22, 2007 4:05 pm

Jaypee

Your code does not display text between tabs which is longer than 8 characters. Also, your tabs are not positioned every 8 characters after the first string character, but rather add spaces to each token to make it 8 characters long - this is not the same thing though!

The following method will convert any string with any tab character and any tab length to a string with the appropriate number of spaces. Use the overloaded methods further below for calls with default properties. Using StringBuffer instead of String increases performance by about 40% though we are talking about 8 microseconds per call (on my machine) anyway...

Code: Select all

public static String tabsToSpaces(String string, char tab, int tabLength)
{
	if (string == null) return null;
	StringBuffer newString = new StringBuffer();
	for (int i = 0; i < string.length(); i++)
	{
		char c = string.charAt(i);
		if (c == tab)
		{
			if (tabLength <= 0) continue;
			int spaces = tabLength - newString.length() % tabLength;
			for (int j = 0; j < spaces; j++) newString.append(" ");
		}
		else
			newString.append(c);
	}
	return newString.toString();
}

public static String tabsToSpaces(String string)
{
	return tabsToSpaces(string, '\t');
}

public static String tabsToSpaces(String string, char tab)
{
	return tabsToSpaces(string, tab, 8);
}
Thomas

jfreeuser2006
Posts: 59
Joined: Mon Nov 20, 2006 1:00 pm

Post by jfreeuser2006 » Fri Feb 23, 2007 6:32 am

tvarsa,

I'll try the code out :-)

Thanks for pointing out the flaw of the code.

josafassj
Posts: 10
Joined: Sat Jul 26, 2008 1:24 pm

NullPointerException

Post by josafassj » Sat Jul 26, 2008 1:30 pm

I'm trying to overwrite the method getitempaint, like you show in this forum, but it returns a NullPointerExeption when I try to access the getValue of the dataset. I'm using the ChartFactory.createLineChart to create a 2D Shape chart. It's OK when I use the default renderer.

Locked