Tooltips not shown in XYZPlot

A discussion forum for JFreeChart (a 2D chart library for the Java platform).
badera
Posts: 9
Joined: Fri Dec 11, 2009 4:13 pm
antibot: No, of course not.

Tooltips not shown in XYZPlot

Post by badera » Tue Dec 15, 2009 2:53 pm

Hi,
I thought this code would be right, but somehow it doesn't show up the tooltip:

Code: Select all

        JFreeChart theChart = createFreeChart( chartDataSet, "Presentation", "[Nm]" ); 
        ChartPanel chartPanel = new ChartPanel( theChart ); 
        theChart.getXYPlot().getRenderer().setBaseToolTipGenerator(new XYToolTipGenerator() { 
            public String generateToolTip(XYDataset dataset, int series, int item) { 
                XYZDataset xyzDataset = (XYZDataset)dataset; 
                double x = xyzDataset.getXValue(series, item); 
                double y = xyzDataset.getYValue(series, item); 
                double z = xyzDataset.getZValue(series, item); 
                System.out.println("Tooltip: x =" + x + " | " + y + " | " + z); 
                return ("" + x + " | " + y + " | " + z); 
            } 
        }); 
        chartPanel.setDisplayToolTips( true );
The System.out shows something like this:
(many many entries like these:)
Tooltip: x =3349.0 | 1200.0 | 22.8504
Tooltip: x =3399.0 | 1200.0 | 22.8504
Tooltip: x =3449.0 | 1200.0 | 23.0352
Tooltip: x =3499.0 | 1200.0 | 23.0352
Tooltip: x =3549.0 | 1200.0 | 23.0352
Tooltip: x =3599.0 | 1200.0 | 23.0352
Tooltip: x =3649.0 | 1200.0 | 23.2104
Tooltip: x =3699.0 | 1200.0 | 23.2104
Tooltip: x =3749.0 | 1200.0 | 23.2104
Tooltip: x =3799.0 | 1200.0 | 23.2104
Tooltip: x =3849.0 | 1200.0 | 23.3778
Tooltip: x =3899.0 | 1200.0 | 23.3778
Tooltip: x =3949.0 | 1200.0 | 23.3778
Tooltip: x =3999.0 | 1200.0 | 23.3778
Tooltip: x =0.0 | 0.0 | 0.0
Tooltip: x =0.0 | 0.0 | 0.0
Tooltip: x =0.0 | 0.0 | 0.0
Tooltip: x =0.0 | 0.0 | 0.0
Tooltip: x =0.0 | 0.0 | 0.0
Tooltip: x =0.0 | 0.0 | 0.0
Tooltip: x =0.0 | 0.0 | 0.0
Tooltip: x =0.0 | 0.0 | 0.0
Tooltip: x =0.0 | 0.0 | 0.0
Tooltip: x =0.0 | 0.0 | 0.0
Tooltip: x =0.0 | 0.0 | 0.0
Tooltip: x =0.0 | 0.0 | 0.0
Tooltip: x =0.0 | 0.0 | 0.0
Tooltip: x =0.0 | 0.0 | 0.0
Followed by many more 0.0 lines.
What am I missing?

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

Re: Tooltips not shown in XYZPlot

Post by paradoxoff » Wed Dec 16, 2009 7:13 pm

Have to tried to call setBaseCreateEntities(true) or setSeriesCreateEntities(0, true)?
In any case I am surprised that your generateToolTip() method is apparently being invoked.
Can you show a larger piece of code?

badera
Posts: 9
Joined: Fri Dec 11, 2009 4:13 pm
antibot: No, of course not.

Re: Tooltips not shown in XYZPlot

Post by badera » Thu Dec 17, 2009 12:32 pm

paradoxoff wrote:Have to tried to call setBaseCreateEntities(true) or setSeriesCreateEntities(0, true)?
In any case I am surprised that your generateToolTip() method is apparently being invoked.
Can you show a larger piece of code?
I didn't try those two methods. Now I have tried, doesn't work either. How much more code do you need to see? I can provide the createFreeChart()-method:

Code: Select all

    private JFreeChart createFreeChart(XYZDataset dataset, String title,
            String yAxisNaming, double dMinZ, double dMaxZ) {
        NumberAxis xAxis = new NumberAxis("X");
         xAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
         xAxis.setLowerMargin(0.0);
         xAxis.setUpperMargin(0.0);
         NumberAxis yAxis = new NumberAxis(yAxisNaming);
         yAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
         yAxis.setLowerMargin(0.0);
         yAxis.setUpperMargin(0.0);
         XYBlockRenderer renderer = new XYBlockRenderer();
         RedScale scale = new RedScale(Math.floor(dMinZ), Math.ceil(dMaxZ));
         renderer.setPaintScale(scale);

         // -------------------------------------------------------------------
         // paint legend
         // -------------------------------------------------------------------
         NumberAxis numberaxis2 = new NumberAxis("scale");
         numberaxis2.setAxisLinePaint(Color.white);
         numberaxis2.setTickMarkPaint(Color.white);
         numberaxis2.setTickLabelFont(new Font("Dialog", 0, 7));
         XYPlot plot = new XYPlot(dataset, xAxis, yAxis, renderer);
         plot.setBackgroundPaint(Color.lightGray);
         plot.setDomainGridlinesVisible(true);
         plot.setRangeGridlinePaint(Color.white);
         JFreeChart chart = new JFreeChart(title, plot);

         PaintScaleLegend paintscalelegend = new PaintScaleLegend(scale,
                        numberaxis2);
         paintscalelegend.setSubdivisionCount(20);
         paintscalelegend.setAxisLocation(AxisLocation.BOTTOM_OR_LEFT);
         paintscalelegend.setAxisOffset(5D);
         paintscalelegend.setMargin(new RectangleInsets(5D, 5D, 5D, 5D));
         paintscalelegend.setFrame(new BlockBorder(Color.red));
         paintscalelegend.setPadding(new RectangleInsets(10D, 10D, 10D, 10D));
         paintscalelegend.setStripWidth(10D);
         paintscalelegend.setPosition(RectangleEdge.RIGHT);
         chart.addSubtitle(paintscalelegend);
         // -------------------------------------------------------------------
         
         return chart;
    }
What confuses me most are the numerous lines "Tooltip: x =0.0 | 0.0 | 0.0". I think that might have to do with the reason why the tooltips aren't shown.

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

Re: Tooltips not shown in XYZPlot

Post by paradoxoff » Thu Dec 17, 2009 8:30 pm

badera wrote: How much more code do you need to see?
All what is neccessary to compile and run it, but no classes that are not part of either the standard JRE or JFreeChart, e. g. no RedScale.
badera wrote: What confuses me most are the numerous lines "Tooltip: x =0.0 | 0.0 | 0.0". I think that might have to do with the reason why the tooltips aren't shown.
Well you haven´t shown the code which creates the dataset. I am not even sure what kind of XYZDataset implementation you are using. A DefaultXYZDataset or something self-programmed?
Does this code produce the expected behaviour?

Code: Select all

import java.awt.Color;
import java.awt.Font;
import java.text.SimpleDateFormat;
import javax.swing.JFrame;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.AxisLocation;
import org.jfree.chart.axis.DateAxis;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.block.BlockBorder;
import org.jfree.chart.labels.XYToolTipGenerator;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.GrayPaintScale;
import org.jfree.chart.renderer.xy.XYItemRenderer;
import org.jfree.chart.renderer.xy.XYBlockRenderer;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.chart.title.PaintScaleLegend;
import org.jfree.data.Range;
import org.jfree.data.time.Day;
import org.jfree.data.time.TimeSeries;
import org.jfree.data.time.TimeSeriesCollection;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYZDataset;
import org.jfree.data.xy.DefaultXYZDataset;
import org.jfree.ui.ApplicationFrame;
import org.jfree.ui.RectangleInsets;
import org.jfree.ui.RectangleEdge;
import org.jfree.ui.RefineryUtilities;


public class XYZToolTipDemo{
    public static void main(String[] args) {
        DefaultXYZDataset dataset = new DefaultXYZDataset();
        dataset.addSeries("Series1", new double[][]{{2.0,1.0,3.0}, {10.0,20.0,30.0}, {10.0,50.0,90.0}});
        JFreeChart chart = createFreeChart(dataset, "Chart Title", "y axis", 0.0, 100.0);
 	    ChartPanel chartPanel = new ChartPanel(chart);
        chart.getXYPlot().getRenderer().setBaseToolTipGenerator(new XYToolTipGenerator() {
            public String generateToolTip(XYDataset dataset, int series, int item) {
                XYZDataset xyzDataset = (XYZDataset)dataset;
                double x = xyzDataset.getXValue(series, item);
                double y = xyzDataset.getYValue(series, item);
                double z = xyzDataset.getZValue(series, item);
                System.out.println("Tooltip: x =" + x + " | " + y + " | " + z);
                return ("" + x + " | " + y + " | " + z);
            }
        });
        chartPanel.setDisplayToolTips( true );
        JFrame frame = new JFrame("XYZToolTipDemo");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setContentPane(chartPanel);
        frame.pack();
        frame.setVisible(true);
    }
    private static JFreeChart createFreeChart(XYZDataset dataset, String title,
            String yAxisNaming, double zMin, double zMax) {
         NumberAxis xAxis = new NumberAxis("X");
         xAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
         xAxis.setLowerMargin(0.0);
         xAxis.setUpperMargin(0.0);
         NumberAxis yAxis = new NumberAxis(yAxisNaming);
         yAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
         yAxis.setLowerMargin(0.0);
         yAxis.setUpperMargin(0.0);
         GrayPaintScale scale = new GrayPaintScale(zMin, zMax);
         XYBlockRenderer renderer = new XYBlockRenderer();
         renderer.setPaintScale(scale);

         // -------------------------------------------------------------------
         // paint legend
         // -------------------------------------------------------------------
         NumberAxis numberaxis2 = new NumberAxis("scale");
         numberaxis2.setAxisLinePaint(Color.white);
         numberaxis2.setTickMarkPaint(Color.white);
         numberaxis2.setTickLabelFont(new Font("Dialog", 0, 7));
         numberaxis2.setRange(new Range(zMin, zMax));
         XYPlot plot = new XYPlot(dataset, xAxis, yAxis, renderer);
         plot.setBackgroundPaint(Color.lightGray);
         plot.setDomainGridlinesVisible(true);
         plot.setRangeGridlinePaint(Color.white);
         JFreeChart chart = new JFreeChart(title, plot);

         PaintScaleLegend paintscalelegend = new PaintScaleLegend(scale,
                        numberaxis2);
         paintscalelegend.setSubdivisionCount(20);
         paintscalelegend.setAxisLocation(AxisLocation.BOTTOM_OR_LEFT);
         paintscalelegend.setAxisOffset(5D);
         paintscalelegend.setMargin(new RectangleInsets(5D, 5D, 5D, 5D));
         paintscalelegend.setFrame(new BlockBorder(Color.red));
         paintscalelegend.setPadding(new RectangleInsets(10D, 10D, 10D, 10D));
         paintscalelegend.setStripWidth(10D);
         paintscalelegend.setPosition(RectangleEdge.RIGHT);
         chart.addSubtitle(paintscalelegend);
         // -------------------------------------------------------------------
         
         return chart;
    }
}

badera
Posts: 9
Joined: Fri Dec 11, 2009 4:13 pm
antibot: No, of course not.

Re: Tooltips not shown in XYZPlot

Post by badera » Fri Dec 18, 2009 10:16 am

paradoxoff wrote:
badera wrote: What confuses me most are the numerous lines "Tooltip: x =0.0 | 0.0 | 0.0". I think that might have to do with the reason why the tooltips aren't shown.
Well you haven´t shown the code which creates the dataset. I am not even sure what kind of XYZDataset implementation you are using. A DefaultXYZDataset or something self-programmed?
It is a "simple" DefaultXYZDataset:

Code: Select all

DefaultXYZDataset chartData;
It is filled with

Code: Select all

double dataSeries[][] = { xValuesSeries, yValuesSeries, zValuesSeries };
chartData.addSeries( seriesName, dataSeries);
where the series are defined like this:

Code: Select all

double[] xValuesSeries = new double[ iNumberOfPoints ];
double[] yValuesSeries = new double[ iNumberOfPoints ];
double[] zValuesSeries = new double[ iNumberOfPoints ];
with iNumberOfPoints = 1296000
paradoxoff wrote: Does this code produce the expected behaviour?
It behaves right, yes, although the System.out does not always show while the tooltip does.

May I ask an additional question? If you look at the attached chart, there are 4 vertical lines which are clearly bold, compared to the other lines. Is this a JFreeChart feature in this example or is this based on some data which I missed? -->
http://www.abload.de/image.php?img=jfre ... 01faq7.jpg

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

Re: Tooltips not shown in XYZPlot

Post by paradoxoff » Fri Dec 18, 2009 4:35 pm

The only obvious, major difference between my sample code and your code is the size of the dataset. Did I get you right that you have indeed 1296000 items? In that case, you will create 1M entities with tooltips which a) might be a challenge for the heap and b) will take some time to render. I believe that either the mere size of the data or the rendering time could prevent the tool tips from showing up. If you can control the size of the dataset, you could try to start with a smaller one.
badera wrote: It behaves right, yes, although the System.out does not always show while the tooltip does.
The output to System.out is only generated when the tool tip string is generated which is happening during the rendering process. The generated tool tips are then stored and simply fetched when they are required, i.e. when the mouse is over region of the screen which is occupied by one of the chart entities which are created during rendering. If you enforce a re-rendering of the chart, i. e. when you resize the chart, you will again see messages at System.out.

badera
Posts: 9
Joined: Fri Dec 11, 2009 4:13 pm
antibot: No, of course not.

Re: Tooltips not shown in XYZPlot

Post by badera » Fri Dec 18, 2009 6:03 pm

paradoxoff wrote:The only obvious, major difference between my sample code and your code is the size of the dataset. Did I get you right that you have indeed 1296000 items? In that case, you will create 1M entities with tooltips which a) might be a challenge for the heap and b) will take some time to render. I believe that either the mere size of the data or the rendering time could prevent the tool tips from showing up. If you can control the size of the dataset, you could try to start with a smaller one.
I have tried with 6480 but still no ToolTips. Are they still too many points??
In the meantime I will try another way to check my dataset.

BTW do you know whether it is possible to fill the squares with some color? If so, how?

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

Re: Tooltips not shown in XYZPlot

Post by paradoxoff » Fri Dec 18, 2009 8:22 pm

Looking at the picture it is clear that you are using the XYBlockRenderer in a quite unusual way, namely as a grid line generator. I am not sure how you have achieved that (probably a very small value for the blockWidth), but it is clear that you will have trouble to really hit the data item (which are apparently just the grid lines) with the mouse.
When I increased the size of the dataset to check how long the rendering would take, I noted that I became more and more difficult to get the tool tips, probably as a result of more and more difficulty to hit the item area.
I was first confused by your question on how to "fill the squares" (because an XYBlockRenderer is already filling the squares with a olor obtained from the paint scale), but after I have seen what you are really doing with your data items, that confusion vanished.
Unfortunately, I have no idea how you could get tool tips for very small data items, even if they are only small along one direction. And I have no idea, based on what you already have, how you could fill the squares.
What if you dropped your color-encodd grid line, and placed some real xyz data items in your plot, preferrably at those locations where you would like the squares to be filled.
If you do so, note that the XYBlockRenderer will use a shape size given by the blockWidth and blockHeight relative to the axis range. If you have large axis range (in your case, ~10000 along both axes), the block width and block height should be around 100 to get a visible and easily handled shape.
If you do not want to worry about that, you could also use an XYShapeRenderer.

badera
Posts: 9
Joined: Fri Dec 11, 2009 4:13 pm
antibot: No, of course not.

Re: Tooltips not shown in XYZPlot

Post by badera » Mon Jan 04, 2010 1:47 pm

paradoxoff wrote:Looking at the picture it is clear that you are using the XYBlockRenderer in a quite unusual way, namely as a grid line generator. I am not sure how you have achieved that (probably a very small value for the blockWidth), but it is clear that you will have trouble to really hit the data item (which are apparently just the grid lines) with the mouse.
To be honest, I have taken the XYBlockChartDemo1 and wanted to modify the greyscale-"cloud" for my intentions. Reading your explanations, now I think to understand the problems.
paradoxoff wrote: I was first confused by your question on how to "fill the squares" (because an XYBlockRenderer is already filling the squares with a olor obtained from the paint scale), but after I have seen what you are really doing with your data items, that confusion vanished.
Unfortunately, I have no idea how you could get tool tips for very small data items, even if they are only small along one direction. And I have no idea, based on what you already have, how you could fill the squares.
Maybe I can leave out the tooltips, will find that out. Anyway, the OutOfMemoryError concerns me more.
paradoxoff wrote: What if you dropped your color-encodd grid line, and placed some real xyz data items in your plot, preferrably at those locations where you would like the squares to be filled.
That is what I am doing (if I understand you right). The problem shows as following:
  • If I fill the space between the points completely, I get an OutOfMemoryError, sooner or later.
  • What is problematic is that the gap between the points is not fixed. It is variable. It is possible to have points like 100-200-300-400-500 or 100-500-900-1300-1700 or 1000-2000-3000-4000-5000 or even 10000, 20000, 30000, 40000, 50000 etc. The dots/points themseves are hard to recognize and not enough to have a web-like presentation. So I have to fill those gaps. But how? If I calculate every single point, I get OutOfMemoryError. How can I decide which points to draw? Every 2nd, 3rd, 10th or 100th point is hard to identify from the values and step width. That is my fundamental problem.
paradoxoff wrote: If you do so, note that the XYBlockRenderer will use a shape size given by the blockWidth and blockHeight relative to the axis range. If you have large axis range (in your case, ~10000 along both axes), the block width and block height should be around 100 to get a visible and easily handled shape.
If you do not want to worry about that, you could also use an XYShapeRenderer.
I will take a look at that renderer, thx for the hints.

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

Re: Tooltips not shown in XYZPlot

Post by paradoxoff » Mon Jan 04, 2010 5:08 pm

I am still not sure what is going on. Where do the "points like 100-200-300-400-500 or 100-500-900-1300-1700 or 1000-2000-3000-4000-5000 or even 10000, 20000, 30000, 40000, 50000" come from? What data is determing the range of the axis? Do we have an addional dataset assigned to the XYPlot, and you only need the XYBlockRenderer to draw the grid lines?
If you want to draw a grid line on the data area which is composed of individual points (and to me it looks like that this is indeed what you are doing), using some real data values seems far too much overhead to me. You will indeed need a huge number of points, in the worst case one data point per pixel (which will be a pain to render), and you might see some artifacts when a some grid lines are rendered by two pixels (such as the bold lines that you have mentioned).
You can create your own renderer (possibly, bot not necessarily derived from XYBLockRenderer or XYShapeRenderer) that does nothing but draws a grid line. Though it is intended that an XYItemRenderer, for every call to drawItem(...), draws a data item as some kind of "normal shape" (circle. rectangle,...), it is not mandatory to do so. Your "GridLineRenderer", in drawItem, could, for example, do the following:
- draw the range and the domain axis submitted as parameters in the drawItem method on an arbitrary Graphics2D (e. g. obtained from a BufferedImage), and extract the ticks fromn the returned AxisState. I have myself experimented with that approach to create a new type of PaintScaleLegend that does not show the z range as continuous color bar but as some kind of "normal legend" with one legend item per tick of the PaintScaleLegend's ValueAxis.
- for every tick of the domain axis, get the data value, let the ValueAxis calculate the Java2D position of the x values, and for every x value, draw a vertical line that spans the entire data area from top to bottom, then for every tick of the range axis, do the same and draw horizontal lines for the y values of the ticks that span the entire data area from left to right.
If you then add an arbitrary XYDataset to the plot that does nothing but returning a series count of 1 and an item count of 1, and assign your renderer to this dataset, XYPlot will invoke drawItem of your renderer automatically and only once. You will also have to make sure that the XYItemRendererState of your GridLineRenderer returns false for getProcessVisibleItemsOnly() (as their will not any real items in the dataset).
If that still doesn`t help, then I will probably have to understand further what you want to achieve.
If you want to tile the XYPlot with colored tiles, then look here and in the thread quoted therein for a possible approach.

badera
Posts: 9
Joined: Fri Dec 11, 2009 4:13 pm
antibot: No, of course not.

Re: Tooltips not shown in XYZPlot

Post by badera » Mon Jan 04, 2010 7:07 pm

paradoxoff wrote:I am still not sure what is going on. Where do the "points like 100-200-300-400-500 or 100-500-900-1300-1700 or 1000-2000-3000-4000-5000 or even 10000, 20000, 30000, 40000, 50000" come from? What data is determing the range of the axis? Do we have an addional dataset assigned to the XYPlot, and you only need the XYBlockRenderer to draw the grid lines?
Well, the values are coming from an XML file which I read. So the range and values might differ. Might be in the hundreds, might be in the thousands or whatsoever.
Maybe I can enlighten you when I show you the base idea of representation I want to reach. This graphic is the ideal version:
http://www.abload.de/image.php?img=3d_d ... e3d200.jpg
As JFreeChart cannot display such 3D charts afaik, I try to "flat" this diagram so that I only need to display x-y-axis and the z-values give the color.
Of course the points do not represent whole lines.
paradoxoff wrote: If that still doesn`t help, then I will probably have to understand further what you want to achieve.
If you want to tile the XYPlot with colored tiles, then look here and in the thread quoted therein for a possible approach.
Maybe this works with my data. Will give it a try when the idea with the XYShapeRenderer does not work. Currently working on that.
I hope my goal is clear now? To have something like http://www.abload.de/image.php?img=3d_d ... e2bum7.jpg
Am I on the right way? If not, how would you build this?

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

Re: Tooltips not shown in XYZPlot

Post by paradoxoff » Mon Jan 04, 2010 9:43 pm

From the image, it looks as if your problem might be related to the ones in the earlier threads.
- The x and y values of the data item are not "random" but equally distributed along the axes, and they do not represent "coordinates" but rather "indices"
- For every data point given by its x and y index, we have a floating point value that needs to be displayed.
If that is true, the major problem that I can see is that the size of the data items will have to be adjusted if the number of data items along one axis is higher than the number of available pixels. However, if no interactivity is needed, you should be able to adjust the data before you create the chart. E. g. if you have 5000 data items along one axis, you could merge them to 500 (one containing the data from 1-10, the next from 11 to 20 asf.), and resize the items of the block renderer accordingly.
Here is a short example that creates 50x50 data items in a data range between 0 and 500 along each axis, i.e. one data item for every 10th index. The block size has been set to 10.0f to account for this "low resolution".

Code: Select all

package mycharts;

import java.awt.BasicStroke;
import java.awt.Graphics2D;
import java.awt.Paint;
import java.awt.geom.Rectangle2D;
import java.io.Serializable;

import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.event.RendererChangeEvent;
import org.jfree.chart.plot.CrosshairState;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.PlotRenderingInfo;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.LookupPaintScale;
import org.jfree.chart.renderer.PaintScale;
import org.jfree.data.Range;
import org.jfree.data.general.DatasetUtilities;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYZDataset;
import org.jfree.ui.RectangleAnchor;

import java.awt.Color;
import java.awt.Paint;
import java.awt.Shape;
import java.awt.Font;
import java.awt.geom.*;
import javax.swing.JPanel;
import org.jfree.chart.*;
import org.jfree.chart.plot.*;
import org.jfree.chart.renderer.xy.*;
import org.jfree.chart.renderer.*;
import org.jfree.data.xy.*;
import org.jfree.chart.axis.*;
import org.jfree.chart.title.*;
import org.jfree.ui.*;

public class XYZChartDemo extends ApplicationFrame {
	static JFreeChart chart;
    public XYZChartDemo(String title) {
        super(title);
        ChartPanel chartPanel = (ChartPanel) createDemoPanel();
        chartPanel.setPreferredSize(new java.awt.Dimension(640, 480));
        chartPanel.setMouseZoomable(true, false);
        setContentPane(chartPanel);
        pack();
        setVisible(true);
        
    }
    private static JFreeChart createChart(XYDataset dataset) {
        NumberAxis xAxis = new NumberAxis("x Axis");
        NumberAxis yAxis = new NumberAxis("y Axis");

        XYPlot plot = new XYPlot(dataset, xAxis, yAxis, null);
        XYBlockRenderer r = new XYBlockRenderer();
        LevelPaintScale lps = new LevelPaintScale(250000);
        r.setPaintScale(lps);
        r.setBlockHeight(10.0f);
        r.setBlockWidth(10.0f);
        plot.setRenderer(r);
		JFreeChart chart = new JFreeChart("Chart Title",JFreeChart.DEFAULT_TITLE_FONT,plot,true);
		chart.removeLegend();
        NumberAxis scaleAxis = new NumberAxis("New Scale");
        scaleAxis.setUpperBound(250000);
        scaleAxis.setAxisLinePaint(Color.white);
        scaleAxis.setTickMarkPaint(Color.white);
        scaleAxis.setTickLabelFont(new Font("Dialog", Font.PLAIN, 12));
        PaintScaleLegend legend = new PaintScaleLegend(lps, 
                scaleAxis);
        legend.setSubdivisionCount(100);
        legend.setAxisLocation(AxisLocation.TOP_OR_RIGHT);
        //legend.setStripOutlineVisible(true);
        legend.setStripOutlinePaint(Color.RED);
        //scaleAxis.setTickLabelFont(new Font("Arial",12,0));
        //legend.setAxisOffset(5.0);
        //legend.setMargin(new RectangleInsets(5, 20, 5, 5));
        legend.setPadding(new RectangleInsets(5, 20, 5, 5));
        legend.setStripWidth(20);
        legend.setPosition(RectangleEdge.LEFT);
        legend.setBackgroundPaint(Color.WHITE);
        chart.addSubtitle(legend);
        chart.setBackgroundPaint(Color.white);
        return chart;
    }
    private static XYZDataset createDataset() {
        DefaultXYZDataset dataset = new DefaultXYZDataset();
        	int items = 500;
	        for(int i=0;i<items;i = i + 10){
		    double[][] data = new double[3][items];
		        for(int j=0;j<items;j = j + 10){
					data[0][j]= i;
					data[1][j]= j;
					data[2][j]= i*j;
        		}
	        dataset.addSeries("Serie "+i,data);
        	}
        return dataset;
    }
    public static JPanel createDemoPanel() {
        //chart = createChartEmpty(createDataset());
        chart = createChart(createDataset());
        return new ChartPanel(chart);
    }
    
    /**
     * Starting point for the demonstration application.
     *
     * @param args  ignored.
     */
    public static void main(String[] args) {
        XYZChartDemo demo = new XYZChartDemo(
                "XYZ Demo");
        //demo.pack();
        //RefineryUtilities.centerFrameOnScreen(demo);
        //demo.setVisible(true);
    }
}
class LevelPaintScale implements PaintScale{
	private double upperBound;
	public LevelPaintScale(double upperBound){
		this.upperBound = upperBound;
	}
	public double getLowerBound(){
		return 0.0;
	}
	public double getUpperBound(){
		return upperBound;
	}
	public Paint getPaint(double value){
		if(value < 0.0 || value > upperBound){
			return Color.GRAY;
		}
		double scaledValue = value/upperBound*511;
		if(scaledValue > 511){
		//System.out.println("Red-green-blue"+0+","+(1022-(int)(scaledValue))+","+255);
			return new Color(255,511-(int)(scaledValue),0);
		}
		if(scaledValue > 511){
		//System.out.println("Red-green-blue"+0+","+255+","+((int)(scaledValue)-511));
			return new Color(0,255,(int)(scaledValue)-511);
		}
		if(scaledValue > 255){
		//System.out.println("Red-green-blue"+(510-(int)(scaledValue))+","+255+","+0);
			return new Color((int)(scaledValue)-255,255,0);
		}
		return new Color(0,(int)(scaledValue),255-(int)(scaledValue));
		
	}
}

badera
Posts: 9
Joined: Fri Dec 11, 2009 4:13 pm
antibot: No, of course not.

Re: Tooltips not shown in XYZPlot

Post by badera » Wed Jan 13, 2010 2:27 pm

Hi,
thx for this example. It looks interesting, but for the moment the XYShapeRenderer instead of the XYBlockRenderer looks promising. Maybe I will investigate that example later on.

ranjeet
Posts: 3
Joined: Sat May 14, 2016 11:39 am
antibot: No, of course not.

Re: Tooltips not shown in XYZPlot

Post by ranjeet » Sat May 14, 2016 12:10 pm

Hi, I want to generate same plot as generated by your code, but with color range from blue (for min value) to red (max value). Can you explain how the class LevelPaintScale is working here?
1. In LevelPaintScale Class, Which value is going as input to the getPaint( whichValue?) method. I checked it by printing, it is not the same value as in dataset (data[2][j]).
2. You are not calling getPaint method anywhere but still it is working?
3. How does 2 if condition with same condtion (scaledValue > 511) affect the output and any particular reason to choose 511?

Thank You!

Regards,
Ranjeet
paradoxoff wrote:From the image, it looks as if your problem might be related to the ones in the earlier threads.
- The x and y values of the data item are not "random" but equally distributed along the axes, and they do not represent "coordinates" but rather "indices"
- For every data point given by its x and y index, we have a floating point value that needs to be displayed.
If that is true, the major problem that I can see is that the size of the data items will have to be adjusted if the number of data items along one axis is higher than the number of available pixels. However, if no interactivity is needed, you should be able to adjust the data before you create the chart. E. g. if you have 5000 data items along one axis, you could merge them to 500 (one containing the data from 1-10, the next from 11 to 20 asf.), and resize the items of the block renderer accordingly.
Here is a short example that creates 50x50 data items in a data range between 0 and 500 along each axis, i.e. one data item for every 10th index. The block size has been set to 10.0f to account for this "low resolution".

Code: Select all

package mycharts;

import java.awt.BasicStroke;
import java.awt.Graphics2D;
import java.awt.Paint;
import java.awt.geom.Rectangle2D;
import java.io.Serializable;

import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.event.RendererChangeEvent;
import org.jfree.chart.plot.CrosshairState;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.PlotRenderingInfo;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.LookupPaintScale;
import org.jfree.chart.renderer.PaintScale;
import org.jfree.data.Range;
import org.jfree.data.general.DatasetUtilities;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYZDataset;
import org.jfree.ui.RectangleAnchor;

import java.awt.Color;
import java.awt.Paint;
import java.awt.Shape;
import java.awt.Font;
import java.awt.geom.*;
import javax.swing.JPanel;
import org.jfree.chart.*;
import org.jfree.chart.plot.*;
import org.jfree.chart.renderer.xy.*;
import org.jfree.chart.renderer.*;
import org.jfree.data.xy.*;
import org.jfree.chart.axis.*;
import org.jfree.chart.title.*;
import org.jfree.ui.*;

public class XYZChartDemo extends ApplicationFrame {
	static JFreeChart chart;
    public XYZChartDemo(String title) {
        super(title);
        ChartPanel chartPanel = (ChartPanel) createDemoPanel();
        chartPanel.setPreferredSize(new java.awt.Dimension(640, 480));
        chartPanel.setMouseZoomable(true, false);
        setContentPane(chartPanel);
        pack();
        setVisible(true);
        
    }
    private static JFreeChart createChart(XYDataset dataset) {
        NumberAxis xAxis = new NumberAxis("x Axis");
        NumberAxis yAxis = new NumberAxis("y Axis");

        XYPlot plot = new XYPlot(dataset, xAxis, yAxis, null);
        XYBlockRenderer r = new XYBlockRenderer();
        LevelPaintScale lps = new LevelPaintScale(250000);
        r.setPaintScale(lps);
        r.setBlockHeight(10.0f);
        r.setBlockWidth(10.0f);
        plot.setRenderer(r);
		JFreeChart chart = new JFreeChart("Chart Title",JFreeChart.DEFAULT_TITLE_FONT,plot,true);
		chart.removeLegend();
        NumberAxis scaleAxis = new NumberAxis("New Scale");
        scaleAxis.setUpperBound(250000);
        scaleAxis.setAxisLinePaint(Color.white);
        scaleAxis.setTickMarkPaint(Color.white);
        scaleAxis.setTickLabelFont(new Font("Dialog", Font.PLAIN, 12));
        PaintScaleLegend legend = new PaintScaleLegend(lps, 
                scaleAxis);
        legend.setSubdivisionCount(100);
        legend.setAxisLocation(AxisLocation.TOP_OR_RIGHT);
        //legend.setStripOutlineVisible(true);
        legend.setStripOutlinePaint(Color.RED);
        //scaleAxis.setTickLabelFont(new Font("Arial",12,0));
        //legend.setAxisOffset(5.0);
        //legend.setMargin(new RectangleInsets(5, 20, 5, 5));
        legend.setPadding(new RectangleInsets(5, 20, 5, 5));
        legend.setStripWidth(20);
        legend.setPosition(RectangleEdge.LEFT);
        legend.setBackgroundPaint(Color.WHITE);
        chart.addSubtitle(legend);
        chart.setBackgroundPaint(Color.white);
        return chart;
    }
    private static XYZDataset createDataset() {
        DefaultXYZDataset dataset = new DefaultXYZDataset();
        	int items = 500;
	        for(int i=0;i<items;i = i + 10){
		    double[][] data = new double[3][items];
		        for(int j=0;j<items;j = j + 10){
					data[0][j]= i;
					data[1][j]= j;
					data[2][j]= i*j;
        		}
	        dataset.addSeries("Serie "+i,data);
        	}
        return dataset;
    }
    public static JPanel createDemoPanel() {
        //chart = createChartEmpty(createDataset());
        chart = createChart(createDataset());
        return new ChartPanel(chart);
    }
    
    /**
     * Starting point for the demonstration application.
     *
     * @param args  ignored.
     */
    public static void main(String[] args) {
        XYZChartDemo demo = new XYZChartDemo(
                "XYZ Demo");
        //demo.pack();
        //RefineryUtilities.centerFrameOnScreen(demo);
        //demo.setVisible(true);
    }
}
class LevelPaintScale implements PaintScale{
	private double upperBound;
	public LevelPaintScale(double upperBound){
		this.upperBound = upperBound;
	}
	public double getLowerBound(){
		return 0.0;
	}
	public double getUpperBound(){
		return upperBound;
	}
	public Paint getPaint(double value){
		if(value < 0.0 || value > upperBound){
			return Color.GRAY;
		}
		double scaledValue = value/upperBound*511;
		if(scaledValue > 511){
		//System.out.println("Red-green-blue"+0+","+(1022-(int)(scaledValue))+","+255);
			return new Color(255,511-(int)(scaledValue),0);
		}
		if(scaledValue > 511){
		//System.out.println("Red-green-blue"+0+","+255+","+((int)(scaledValue)-511));
			return new Color(0,255,(int)(scaledValue)-511);
		}
		if(scaledValue > 255){
		//System.out.println("Red-green-blue"+(510-(int)(scaledValue))+","+255+","+0);
			return new Color((int)(scaledValue)-255,255,0);
		}
		return new Color(0,(int)(scaledValue),255-(int)(scaledValue));
		
	}
}

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

Re: Tooltips not shown in XYZPlot

Post by paradoxoff » Sat May 14, 2016 8:35 pm

THe getPaint() method of the PaintScale is called by the XYBlockRenderer or XZShapeRenderer and also by the PaintScaleLegend.
If the method is called from the renderer, that means that the renderer wants to get a suitable color to render the z value of the dataset. In this case, the value parameter of the getPaint-method should exactly match the value in your dataset. If this method is called from the PaintScaleLegend, the situation is different. The PaintScaleLegend will divide the range of the ValueAxis in a number of sections or subdivision that have the same color. This color will be queried from the PaintScale, and the argument will the vaalues at the edges of the subdivisions, regardless of whether the dataset contains a value with that z value or not.
The upper value of 511 comes from my definition of the color range:
Values within the upper 50 % (scaledValue > 255) of the range of the paintscale will be drawn in a color composed of green and an increasing amount of red. The color gradient will thus be from green to yellow.
Values in the lower 50 % will be drawn in a color with an increasing amount of green and a decresasing amount of blue, and the gradient will be from blue to green.
Overall you will get a color gradient from blue to yellow.
In order to get a change from red to blue, you could change the upper limit from 511 to 255 so that the scaledValue will be between 0 and 255, and then return a Color ((int)(255-scaledValue), 0, (int)scaledValue). That will give you a color gradient from pure red (scaledValue near or at zero) and pure blue (scaledValue near or at 255).

Locked