MinMaxCategoryDataset: how to change item lines/icons

A discussion forum for JFreeChart (a 2D chart library for the Java platform).
Locked
mhilpert
Posts: 497
Joined: Wed Apr 02, 2003 1:57 pm
Location: Germany

MinMaxCategoryDataset: how to change item lines/icons

Post by mhilpert » Mon Jun 24, 2013 4:59 pm

The refernce manual doesn't tell much about this rendere, alas. I would like to change the min/middle/max item marks. Unfortunately, I can set a null icons (this works in play Java, but when exported this in SVG and integrated in FOP PDF page, I get a NullPointerException). So I create a small transparent image and call setMinIcon()/setMaxIcon().

So far, so good. But then I'm left with little lines that I want to change. I would like to change the line color/length/thickness but the API doesn't offer this - except setSeriesPaint() but this only works in a small test case - not in a large JFReeChart with many JFreeChart calls, datasets, settings.

I tried to call setSeriesOutlineStroke() but this also doesn't change anything or change the length of all (!) lines. In addition they are not cenetered!

When I try to work around this with ugly custom icons, these icons are not centered, too! They are glued at the right side of the vertical line.
Java 11, JFreeChart 1.0.15, JFreeSVG 4.0

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

Re: MinMaxCategoryDataset: how to change item lines/icons

Post by paradoxoff » Tue Jun 25, 2013 8:39 pm

mhilpert wrote:The refernce manual doesn't tell much about this rendere, alas. I would like to change the min/middle/max item marks. Unfortunately, I can set a null icons (this works in play Java, but when exported this in SVG and integrated in FOP PDF page, I get a NullPointerException).
Shouldn´t "can" be replaced by "can´t"? According to the source, attempted use of a null Icon for a MinMaxCategoryRenderer should lead to an IllegalArgumentException.
mhilpert wrote: So far, so good. But then I'm left with little lines that I want to change. I would like to change the line color/length/thickness but the API doesn't offer this - except setSeriesPaint() but this only works in a small test case - not in a large JFReeChart with many JFreeChart calls, datasets, settings.
Does "this only works in a small test case - not in a large JFreeChart" mean "its too complicated to set all series paints in a large JFreeChart"? In this case, I would suggest to create your own DrawingSupplier with an order of paints that you like more than those in a DefaultDrawingSupplier. If not: you probably know that "it doesn´t work" is not a good error description.
mhilpert wrote: I tried to call setSeriesOutlineStroke() but this also doesn't change anything or change the length of all (!) lines. In addition they are not cenetered!
setSeriesStroke() is the way to go. Note that this only changes the thickness of the "little lines" (you are probably talking about the objectIcons). The length of the lines is hardcoded, since the default objectIcons are special icons generated by ythe renderer itself which simply draw a line of length 8 (from x=-4 to x=4) in the paintIcon() method. The stroke and paint of the Graphics2D are not modified. By defaualt, the return values of getItemPaint() and getItemStroke() are used. I wonder how a call to setSeriesOutlineStroke() should change things. As far as I have seen, the seriesOutlineStroke is never used in the drawItem method of the MinMaxRenderer! Can you show some code?
mhilpert wrote: When I try to work around this with ugly custom icons, these icons are not centered, too! They are glued at the right side of the vertical line.
As outlined above, one feature of the objectIcons (and also of the other default icons of the MinMaxRenderer) is that they are centered around the x,y, coordinates supplied in the paintIcon() method. A normal ImageIcon does not have that features. You could create a wrapper around an ImageIcon that translates the Graphics2D by -x/2 and -y/2 before painting the ImageIcon itself.

All in all, I would strongly suggest to simply look at the source code. IMHO, thats an extremely valuable source of information. And it comes for free.

edit: here is a piece of code that is showing a few things. In my hands, most thinks worked as expected.

Code: Select all

public class MinMaxChart extends ApplicationFrame {

    public MinMaxChart(String title) {
        super(title);

        final CategoryDataset dataset = createDataset();
        final JFreeChart chart = createChart(dataset);
        final ChartPanel chartPanel = new ChartPanel(chart);
        chartPanel.setPreferredSize(new java.awt.Dimension(500, 350));
        setContentPane(chartPanel);
    }

    private CategoryDataset createDataset() {
        double[][] data = new double[][]{
            {1, 5, 3, 7},
            {2, 3, 8, 5},
            {3, 11, 7, 4}
        };
        return DatasetUtilities.createCategoryDataset(
                "Category ", "Serie", data);
    }

    private JFreeChart createChart(final CategoryDataset dataset) {
        MinMaxCategoryRenderer renderer = new MinMaxCategoryRenderer();
        renderer.setSeriesPaint(0, new Color(255, 0, 255));
        renderer.setSeriesPaint(1, Color.green);
        renderer.setSeriesPaint(2, Color.orange.darker());
        renderer.setSeriesStroke(2, new BasicStroke(3.0f));
        renderer.setObjectIcon(getIcon(new Line2D.Double(-12, 0, 12, 0), true, true));
        renderer.setDrawLines(true);
        CategoryPlot plot = new CategoryPlot(dataset, new CategoryAxis("Categories"), new NumberAxis("Values"), renderer);
        return new JFreeChart(plot);
    }

    public static void main(final String[] args) {

        final MinMaxChart demo =
                new MinMaxChart("Stacked Bar Chart");
        demo.pack();
        RefineryUtilities.centerFrameOnScreen(demo);
        demo.setVisible(true);
    }
    private Icon getIcon(Shape shape, final boolean fill,
            final boolean outline) {
        final int width = shape.getBounds().width;
        final int height = shape.getBounds().height;
        final GeneralPath path = new GeneralPath(shape);
        return new Icon() {
            public void paintIcon(Component c, Graphics g, int x, int y) {
                Graphics2D g2 = (Graphics2D) g;
                path.transform(AffineTransform.getTranslateInstance(x, y));
                if (fill) {
                    g2.fill(path);
                }
                if (outline) {
                    g2.draw(path);
                }
                path.transform(AffineTransform.getTranslateInstance(-x, -y));
            }

            public int getIconWidth() {
                return width;
            }

            public int getIconHeight() {
                return height;
            }
        };
    }
}

mhilpert
Posts: 497
Joined: Wed Apr 02, 2003 1:57 pm
Location: Germany

Re: MinMaxCategoryDataset: how to change item lines/icons

Post by mhilpert » Tue Jun 25, 2013 10:19 pm

I _did_ inspect the source code and I am disapponted about the few public methods to configure the min/max lines! This is my problem in the first place! My simple test method code above is all to show the different bugs of JFreeChart - it's just awful how buggy this renderer is! The first bug is the different plots of the same code - just startet multiple times shows a different chart each time. Sometimes lines are missing, sometimes the "horizontal" lines are "angled" instead of horizontal, sometimes the colors are okay - sometimes they are just random. I would laugh it it was a joke ... but it isn't.
Java 11, JFreeChart 1.0.15, JFreeSVG 4.0

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

Re: MinMaxCategoryDataset: how to change item lines/icons

Post by paradoxoff » Wed Jun 26, 2013 7:08 pm

mhilpert wrote:I _did_ inspect the source code and I am disapponted about the few public methods to configure the min/max lines! This is my problem in the first place!
Well you can represent the min/max points by Icons. This gives you a large number of options, more than any combination of shape/stroke/etc. Can you specify what you would need on top of that?
In general: if a renderer doesn´t fulfill your specific needs, write your own renderer that does what you want.
mhilpert wrote:My simple test method code above is all to show the different bugs of JFreeChart - it's just awful how buggy this renderer is! The first bug is the different plots of the same code - just startet multiple times shows a different chart each time. Sometimes lines are missing, sometimes the "horizontal" lines are "angled" instead of horizontal, sometimes the colors are okay - sometimes they are just random.
I ran your code (i.e. I copied your method to an own class and ran that) a couple of times and got the same result each time. I couldn´t observe any of the things that you mentioned. As mentioned above: the code for the drawItem method of the renderer looks ok. The only thing I could imagine is that the translation of the objectIcons (which are basically horizontal lines with a length of 8 that are cloaked as Icons) sometimes gives screen coordinates for the y cordinates of start and end point of the line that are off by 1 pixel. That would look like an skew line. In my runs, I have never observed it.
Regarding the sometimes ok, sometimes random colors: No idea where that could come from, unless you are using differently configured DrawingSuppliers. If you can´t describe better what you have done (ideally by providing an SSCCE) and what was the result, I´d need to give up.

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

Re: MinMaxCategoryDataset: how to change item lines/icons

Post by david.gilbert » Wed Jul 03, 2013 2:03 pm

In this renderer I don't think the use of the Icon class adds a lot of value, in fact it makes the API harder to work with. Do you have an example of the type of chart you are trying to create? It sounds like modifying an existing renderer a little might be a cleaner solution.
David Gilbert
JFreeChart Project Leader

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

mhilpert
Posts: 497
Joined: Wed Apr 02, 2003 1:57 pm
Location: Germany

Re: MinMaxCategoryDataset: how to change item lines/icons

Post by mhilpert » Wed Jul 03, 2013 7:14 pm

Well, we just like to change the 3 item points to horizontal lines with their own length, thickness, color, ... it would be nice to have a selection of other symbols that can be used for min/middle/max; e.g. like the chart legend items.
Java 11, JFreeChart 1.0.15, JFreeSVG 4.0

Locked