Search code examples
javachartsjfreechartappearance

JFreeChart chart.getWidth() not working when trying to left-align subtitle to centered title


I am trying to left-align a JFreeChart subtitle to a centered title such that the main title is centered in the ChartFrame but the subtitle is aligned to the left margin of the title. The only way I could think to do this was to set the title and subtitle to have a HorizontalAlignment.LEFT. Then I'd have the program manually set the left padding of the title such that it was centered, and then set the subtitle padding to match that of the title, thereby lining them up to the same left-margin which is calculated to line the title up to the center of the frame like this:

// Make the chart
JFreeChart chart = ChartFactory.createTimeSeriesChart(title, "Time (Hour)", "Vehicles Parked", dataset, true, true, false);

ChartFrame frame = new ChartFrame("Chart", chart);
frame.pack();
frame.setVisible(true);

chart.getTitle().setHorizontalAlignment(HorizontalAlignment.LEFT);
chart.getTitle().setPadding(0, (frame.getWidth()/2)-(chart.getTitle().getWidth()/2), 0, 0);

TextTitle subtitle1 = new TextTitle(
        "This is a test subtitle in which I would like\nthe subtitle to be lined up to the title", // text
        chart.getTitle().getFont().deriveFont(chart.getTitle().getFont().getSize() * 0.6f), // font (shrunk title)
        chart.getTitle().getPaint(), // paint
        RectangleEdge.TOP, // position
        HorizontalAlignment.LEFT, //chart2.getTitle().DEFAULT_HORIZONTAL_ALIGNMENT, // horizontal alignment
        VerticalAlignment.BOTTOM, // vertical alignment
        chart.getTitle().getPadding() // padding
);
chart.addSubtitle(subtitle1);

In trying to do this, the chart.getTitle().getWidth() method is returning 0.0 every time, and I can't figure out why. I have tried casting chart.getTitle() to an AbstractBlock but that makes no difference. I believe it has something to do with the fact that in the JavaDoc for the getWidth() method in the AbstractBlock class, it mentions it will return the width if it knows it in advance, which apparently it doesn't.

I want to know how to get the chart title to correctly return its width, whether by using the getWidth() function or not. I would also like to know if there is a better way to align elements of a chart to each other as opposed to the sides of the ChartFrame rather than adjusting their padding.

Cross posted here.


Solution

  • As answered here.

    What I had to do to align subtitles to the left margin of the title, but keep the whole thing aligned to the center of the frame was to put both elements into a BlockContainer with a ColumnArrangement, and then create a CompositeTitle from the BlockContainer, and align that CompositeTitle accordingly.

    JFreeChart chart = ChartFactory.createXYLineChart(
            "Has to have a wider title than subtitle", // chart title
            "X", // x axis label
            "Y", // y axis label
            dataset, // data
            PlotOrientation.VERTICAL,
            true, // include legend
            true, // tooltips
            false // urls
    );
    
    String subtitleText = "This is a test subtitle\nIt is also a test of whether or not newlines work";
    
    TextTitle subtitle = new TextTitle(
            subtitleText, // text
            chart.getTitle().getFont().deriveFont(chart.getTitle().getFont().getSize() * 0.6f), // font (shrunk title)
            chart.getTitle().getPaint(), // paint
            RectangleEdge.TOP, // position
            HorizontalAlignment.LEFT, //chart2.getTitle().DEFAULT_HORIZONTAL_ALIGNMENT, // horizontal alignment
            VerticalAlignment.BOTTOM, // vertical alignment
            chart.getTitle().getPadding() // padding
    );
    
    BlockContainer blockContainer = new BlockContainer(new ColumnArrangement(HorizontalAlignment.LEFT, VerticalAlignment.TOP, 0, 0));
    blockContainer.add(chart.getTitle());
    blockContainer.add(subtitle);
    CompositeTitle compositeTitle = new CompositeTitle(blockContainer);
    compositeTitle.setPosition(RectangleEdge.TOP);
    compositeTitle.setVerticalAlignment(VerticalAlignment.CENTER);
    chart.getTitle().setVisible(false);
    chart.addSubtitle(compositeTitle);
    
    ChartFrame frame = new ChartFrame("Frame", chart);
    frame.pack();
    frame.setVisible(true);