The JFree Chart Class Library Developer Guide V1 0 9
User Manual:
Open the PDF directly: View PDF .
Page Count: 805
Download | |
Open PDF In Browser | View PDF |
The JFreeChart Class Library Version 1.0.9 Developer Guide Written by David Gilbert January 7, 2008 c 2000-2008, Object Refinery Limited. All rights reserved. IMPORTANT NOTICE: We work hard to make this document as accurate and informative as we can, but cannot guarantee that it is error-free. Contents 1 Introduction 1.1 What is JFreeChart? . . . . 1.2 This Document . . . . . . . 1.3 Acknowledgements . . . . . 1.4 Comments and Suggestions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 16 18 18 18 2 Sample Charts 2.1 Introduction . . . . . . . . . . . 2.2 Pie Charts . . . . . . . . . . . . 2.3 Bar Charts . . . . . . . . . . . 2.4 Line Chart . . . . . . . . . . . 2.5 XY Plots . . . . . . . . . . . . 2.6 Time Series Charts . . . . . . . 2.7 Histograms . . . . . . . . . . . 2.8 Area Charts . . . . . . . . . . . 2.9 Difference Chart . . . . . . . . 2.10 Step Chart . . . . . . . . . . . 2.11 Gantt Chart . . . . . . . . . . . 2.12 Multiple Axis Charts . . . . . . 2.13 Combined and Overlaid Charts 2.14 Future Development . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 19 19 21 23 24 25 26 27 27 29 30 31 32 33 3 Downloading and Installing JFreeChart 3.1 Introduction . . . . . . . . . . . . . . . . . 3.2 Download . . . . . . . . . . . . . . . . . . 3.3 Unpacking the Files . . . . . . . . . . . . 3.4 Running the Demonstration Applications 3.5 Configuring JFreeChart for use in IDEs . 3.6 Compiling the Source . . . . . . . . . . . 3.7 Generating the Javadoc Documentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34 34 34 34 35 36 36 36 . . . . 4 Using JFreeChart 37 4.1 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 4.2 Creating Your First Chart . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 5 Pie 5.1 5.2 5.3 5.4 5.5 5.6 5.7 Charts Introduction . . . . . . . . . . . Creating a Simple Pie Chart . . Section Colours . . . . . . . . . Section Outlines . . . . . . . . Null, Zero and Negative Values Section and Legend Labels . . . Exploded Sections . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40 40 40 40 41 41 42 42 CONTENTS 5.8 5.9 6 Bar 6.1 6.2 6.3 6.4 6.5 2 3D Pie Charts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Multiple Pie Charts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43 43 Charts Introduction . . . . . . . . . A Bar Chart . . . . . . . . The ChartFactory Class . . Simple Chart Customisation Customising the Renderer . 45 45 45 48 48 49 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 Line Charts 51 7.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51 7.2 A Line Chart Based On A Category Dataset . . . . . . . . . . . . . . . . . . . . . . 51 7.3 A Line Chart Based On An XYDataset . . . . . . . . . . . . . . . . . . . . . . . . . 56 8 Time Series Charts 61 8.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61 8.2 Time Series Charts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61 9 Customising Charts 9.1 Introduction . . . 9.2 Chart Attributes 9.3 Plot Attributes . 9.4 Axis Attributes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67 67 67 69 70 10 Dynamic Charts 72 10.1 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72 10.2 Background . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72 10.3 The Demo Application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73 11 Tooltips 11.1 Overview . . . . . . . 11.2 Generating Tool Tips . 11.3 Collecting Tool Tips . 11.4 Displaying Tool Tips . 11.5 Disabling Tool Tips . 11.6 Customising Tool Tips . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77 77 77 78 78 78 78 12 Item Labels 12.1 Introduction . . . . . . . . . . . . . . . 12.2 Displaying Item Labels . . . . . . . . . 12.3 Item Label Appearance . . . . . . . . 12.4 Item Label Positioning . . . . . . . . . 12.5 Customising the Item Label Text . . . 12.6 Example 1 - Values Above a Threshold 12.7 Example 2 - Displaying Percentages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79 79 80 81 82 83 84 87 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 Multiple Axes and Datasets 91 13.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91 13.2 An Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91 13.3 Hints and Tips . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93 CONTENTS 3 14 Combined Charts 14.1 Introduction . . . . . . . . . . . . 14.2 Combined Domain Category Plot 14.3 Combined Range Category Plot . 14.4 Combined Domain XY Plot . . . 14.5 Combined Range XY Plot . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 Datasets and JDBC 15.1 Introduction . . . . . . . 15.2 About JDBC . . . . . . 15.3 Sample Data . . . . . . 15.4 PostgreSQL . . . . . . . 15.5 The JDBC Driver . . . 15.6 The Demo Applications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99 . 99 . 99 . 99 . 100 . 101 . 102 PDF . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 Exporting Charts to Acrobat 16.1 Introduction . . . . . . . . . 16.2 What is Acrobat PDF? . . 16.3 iText . . . . . . . . . . . . . 16.4 Graphics2D . . . . . . . . . 16.5 Getting Started . . . . . . . 16.6 The Application . . . . . . 16.7 Viewing the PDF File . . . 16.8 Unicode Characters . . . . . 17 Exporting Charts to SVG 17.1 Introduction . . . . . . . 17.2 Background . . . . . . . 17.3 A Sample Application . . . . . . . . . . . . . . . . . . . 94 94 94 95 96 97 103 103 103 103 103 104 104 108 108 Format 111 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111 18 Applets 114 18.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114 18.2 Issues . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114 18.3 A Sample Applet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115 19 Servlets 19.1 Introduction . . . . . . . . . . . . . 19.2 A Simple Servlet . . . . . . . . . . 19.3 Compiling the Servlet . . . . . . . 19.4 Deploying the Servlet . . . . . . . 19.5 Embedding Charts in HTML Pages 19.6 Supporting Files . . . . . . . . . . 19.7 Deploying Servlets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118 118 118 120 121 121 126 127 20 Miscellaneous 20.1 Introduction . . . . . 20.2 X11 / Headless Java 20.3 Java Server Pages . . 20.4 Loading Images . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129 129 129 129 129 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 Packages 130 21.1 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130 CONTENTS 22 Package: org.jfree.chart 22.1 Overview . . . . . . . 22.2 ChartColor . . . . . . 22.3 ChartFactory . . . . . 22.4 ChartFrame . . . . . . 22.5 ChartMouseEvent . . 22.6 ChartMouseListener . 22.7 ChartPanel . . . . . . 22.8 ChartRenderingInfo . 22.9 ChartUtilities . . . . . 22.10ClipPath . . . . . . . . 22.11DrawableLegendItem . 22.12Effect3D . . . . . . . . 22.13HashUtilities . . . . . 22.14JFreeChart . . . . . . 22.15LegendItem . . . . . . 22.16LegendItemCollection 22.17LegendItemSource . . 22.18LegendRenderingOrder 22.19PolarChartPanel . . . 4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131 131 131 131 134 135 136 136 141 142 144 144 144 145 145 150 152 153 154 154 23 Package: org.jfree.chart.annotations 23.1 Overview . . . . . . . . . . . . . . . 23.2 AbstractXYAnnotation . . . . . . . 23.3 CategoryAnnotation . . . . . . . . . 23.4 CategoryLineAnnotation . . . . . . . 23.5 CategoryPointerAnnotation . . . . . 23.6 CategoryTextAnnotation . . . . . . . 23.7 TextAnnotation . . . . . . . . . . . . 23.8 XYAnnotation . . . . . . . . . . . . 23.9 XYBoxAnnotation . . . . . . . . . . 23.10XYDrawableAnnotation . . . . . . . 23.11XYImageAnnotation . . . . . . . . . 23.12XYLineAnnotation . . . . . . . . . . 23.13XYPointerAnnotation . . . . . . . . 23.14XYPolygonAnnotation . . . . . . . . 23.15XYShapeAnnotation . . . . . . . . . 23.16XYTextAnnotation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155 155 155 157 157 159 161 162 164 165 166 167 168 169 171 173 174 24 Package: org.jfree.chart.axis 24.1 Overview . . . . . . . . . . 24.2 Axis . . . . . . . . . . . . . 24.3 AxisCollection . . . . . . . 24.4 AxisLocation . . . . . . . . 24.5 AxisSpace . . . . . . . . . . 24.6 AxisState . . . . . . . . . . 24.7 CategoryAnchor . . . . . . 24.8 CategoryAxis . . . . . . . . 24.9 CategoryAxis3D . . . . . . 24.10CategoryLabelPosition . . . 24.11CategoryLabelPositions . . 24.12CategoryLabelWidthType . 24.13CategoryTick . . . . . . . . 24.14ColorBar . . . . . . . . . . 24.15CompassFormat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 177 177 177 182 182 183 183 184 184 189 190 191 191 192 192 192 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . CONTENTS 24.16CyclicNumberAxis . . . 24.17DateAxis . . . . . . . . 24.18DateTickMarkPosition . 24.19DateTick . . . . . . . . 24.20DateTickUnit . . . . . . 24.21ExtendedCategoryAxis . 24.22LogAxis . . . . . . . . . 24.23LogarithmicAxis . . . . 24.24MarkerAxisBand . . . . 24.25ModuloAxis . . . . . . . 24.26MonthDateFormat . . . 24.27NumberAxis . . . . . . . 24.28NumberAxis3D . . . . . 24.29NumberTick . . . . . . . 24.30NumberTickUnit . . . . 24.31PeriodAxis . . . . . . . 24.32PeriodAxisLabelInfo . . 24.33QuarterDateFormat . . 24.34SegmentedTimeline . . . 24.35StandardTickUnitSource 24.36SubCategoryAxis . . . . 24.37SymbolAxis . . . . . . . 24.38Tick . . . . . . . . . . . 24.39TickType . . . . . . . . 24.40TickUnit . . . . . . . . . 24.41TickUnits . . . . . . . . 24.42TickUnitSource . . . . . 24.43Timeline . . . . . . . . . 24.44ValueAxis . . . . . . . . 24.45ValueTick . . . . . . . . 5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 193 194 198 198 199 200 200 203 204 205 206 207 211 212 213 214 216 218 218 219 220 221 223 223 223 224 225 225 226 229 25 Package: org.jfree.chart.block 25.1 Introduction . . . . . . . . . . 25.2 AbstractBlock . . . . . . . . . 25.3 Arrangement . . . . . . . . . 25.4 Block . . . . . . . . . . . . . 25.5 BlockBorder . . . . . . . . . . 25.6 BlockContainer . . . . . . . . 25.7 BlockFrame . . . . . . . . . . 25.8 BlockParams . . . . . . . . . 25.9 BlockResult . . . . . . . . . . 25.10BorderArrangement . . . . . 25.11CenterArrangement . . . . . 25.12ColorBlock . . . . . . . . . . 25.13ColumnArrangement . . . . . 25.14EmptyBlock . . . . . . . . . . 25.15EntityBlockParams . . . . . . 25.16EntityBlockResult . . . . . . 25.17FlowArrangement . . . . . . . 25.18GridArrangement . . . . . . . 25.19LabelBlock . . . . . . . . . . 25.20LengthConstraintType . . . . 25.21LineBorder . . . . . . . . . . 25.22RectangleConstraint . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 231 231 231 233 234 234 235 237 237 237 238 238 238 239 240 240 240 240 241 241 243 243 244 CONTENTS 26 Package: org.jfree.chart.editor 26.1 Introduction . . . . . . . . . . 26.2 ChartEditor . . . . . . . . . . 26.3 ChartEditorFactory . . . . . 26.4 ChartEditorManager . . . . . 26.5 DefaultAxisEditor . . . . . . 26.6 DefaultChartEditor . . . . . . 26.7 DefaultChartEditorFactory . 26.8 DefaultColorBarEditor . . . . 26.9 DefaultNumberAxisEditor . . 26.10DefaultPlotEditor . . . . . . 26.11DefaultTitleEditor . . . . . . 26.12PaletteChooserPanel . . . . . 26.13PaletteSample . . . . . . . . . 6 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 246 246 246 246 247 247 247 248 248 249 249 249 249 250 27 Package: org.jfree.chart.encoders 27.1 Introduction . . . . . . . . . . . . 27.2 EncoderUtil . . . . . . . . . . . . 27.3 ImageEncoderFactory . . . . . . 27.4 ImageEncoder . . . . . . . . . . . 27.5 ImageFormat . . . . . . . . . . . 27.6 KeyPointPNGEncoderAdapter . 27.7 SunJPEGEncoderAdapter . . . . 27.8 SunPNGEncoderAdapter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 251 251 251 252 253 253 253 254 255 28 Package: org.jfree.chart.entity 28.1 Introduction . . . . . . . . . . 28.2 Background . . . . . . . . . . 28.3 CategoryItemEntity . . . . . 28.4 ChartEntity . . . . . . . . . . 28.5 ContourEntity . . . . . . . . 28.6 EntityCollection . . . . . . . 28.7 LegendItemEntity . . . . . . 28.8 PieSectionEntity . . . . . . . 28.9 StandardEntityCollection . . 28.10TickLabelEntity . . . . . . . 28.11XYAnnotationEntity . . . . . 28.12XYItemEntity . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 256 256 256 256 258 258 259 259 260 260 261 262 262 29 Package: org.jfree.chart.event 29.1 Introduction . . . . . . . . . . 29.2 AxisChangeEvent . . . . . . . 29.3 AxisChangeListener . . . . . 29.4 ChartChangeEvent . . . . . . 29.5 ChartChangeEventType . . . 29.6 ChartChangeListener . . . . . 29.7 ChartProgressEvent . . . . . 29.8 ChartProgressListener . . . . 29.9 MarkerChangeEvent . . . . . 29.10MarkerChangeListener . . . . 29.11PlotChangeEvent . . . . . . . 29.12PlotChangeListener . . . . . 29.13RendererChangeEvent . . . . 29.14RendererChangeListener . . . 29.15TitleChangeEvent . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 263 263 263 263 264 264 265 265 266 266 267 267 268 268 268 269 . . . . . . . . . . . . . CONTENTS 7 29.16TitleChangeListener . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 269 30 Package: org.jfree.chart.imagemap 30.1 Overview . . . . . . . . . . . . . . . . . . . . 30.2 DynamicDriveToolTipTagFragmentGenerator 30.3 ImageMapUtilities . . . . . . . . . . . . . . . 30.4 OverLIBToolTipTagFragmentGenerator . . . 30.5 StandardToolTipTagFragmentGenerator . . . 30.6 StandardURLTagFragmentGenerator . . . . . 30.7 ToolTipTagFragmentGenerator . . . . . . . . 30.8 URLTagFragmentGenerator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 270 270 270 270 271 271 272 272 273 31 Package: org.jfree.chart.labels 31.1 Introduction . . . . . . . . . . . . . . . . 31.2 AbstractCategoryItemLabelGenerator . 31.3 AbstractPieItemLabelGenerator . . . . . 31.4 AbstractXYItemLabelGenerator . . . . 31.5 BoxAndWhiskerToolTipGenerator . . . 31.6 BoxAndWhiskerXYToolTipGenerator . 31.7 CategoryItemLabelGenerator . . . . . . 31.8 CategorySeriesLabelGenerator . . . . . 31.9 CategoryToolTipGenerator . . . . . . . 31.10ContourToolTipGenerator . . . . . . . . 31.11CustomXYToolTipGenerator . . . . . . 31.12HighLowItemLabelGenerator . . . . . . 31.13IntervalCategoryItemLabelGenerator . . 31.14IntervalCategoryToolTipGenerator . . . 31.15ItemLabelAnchor . . . . . . . . . . . . . 31.16ItemLabelPosition . . . . . . . . . . . . 31.17MultipleXYSeriesLabelGenerator . . . . 31.18PieSectionLabelGenerator . . . . . . . . 31.19PieToolTipGenerator . . . . . . . . . . . 31.20StandardCategoryItemLabelGenerator . 31.21StandardCategorySeriesLabelGenerator 31.22StandardCategoryToolTipGenerator . . 31.23StandardContourToolTipGenerator . . . 31.24StandardPieSectionLabelGenerator . . . 31.25StandardPieToolTipGenerator . . . . . . 31.26StandardXYItemLabelGenerator . . . . 31.27StandardXYSeriesLabelGenerator . . . . 31.28StandardXYToolTipGenerator . . . . . 31.29StandardXYZToolTipGenerator . . . . . 31.30SymbolicXYItemLabelGenerator . . . . 31.31XYItemLabelGenerator . . . . . . . . . 31.32XYSeriesLabelGenerator . . . . . . . . . 31.33XYToolTipGenerator . . . . . . . . . . . 31.34XYZToolTipGenerator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 274 274 274 275 276 278 278 278 279 279 280 280 280 281 282 282 283 284 285 286 286 287 288 289 289 291 292 293 294 295 296 296 296 297 297 32 Package: org.jfree.chart.needle 32.1 Overview . . . . . . . . . . . 32.2 ArrowNeedle . . . . . . . . . 32.3 LineNeedle . . . . . . . . . . 32.4 LongNeedle . . . . . . . . . . 32.5 MeterNeedle . . . . . . . . . . 32.6 PinNeedle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 299 299 299 300 300 300 301 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . CONTENTS 32.7 PlumNeedle . 32.8 PointerNeedle 32.9 ShipNeedle . 32.10WindNeedle . 8 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 301 302 302 302 33 Package: org.jfree.chart.plot 33.1 Overview . . . . . . . . . . . . 33.2 CategoryMarker . . . . . . . . 33.3 CategoryPlot . . . . . . . . . . 33.4 ColorPalette . . . . . . . . . . . 33.5 CombinedDomainCategoryPlot 33.6 CombinedDomainXYPlot . . . 33.7 CombinedRangeCategoryPlot . 33.8 CombinedRangeXYPlot . . . . 33.9 CompassPlot . . . . . . . . . . 33.10ContourPlot . . . . . . . . . . . 33.11ContourPlotUtilities . . . . . . 33.12ContourValuePlot . . . . . . . 33.13CrosshairState . . . . . . . . . 33.14DatasetRenderingOrder . . . . 33.15DefaultDrawingSupplier . . . . 33.16DialShape . . . . . . . . . . . . 33.17DrawingSupplier . . . . . . . . 33.18FastScatterPlot . . . . . . . . . 33.19GreyPalette . . . . . . . . . . . 33.20IntervalMarker . . . . . . . . . 33.21Marker . . . . . . . . . . . . . . 33.22MeterInterval . . . . . . . . . . 33.23MeterPlot . . . . . . . . . . . . 33.24MultiplePiePlot . . . . . . . . . 33.25PieLabelDistributor . . . . . . 33.26PieLabelRecord . . . . . . . . . 33.27PiePlot . . . . . . . . . . . . . 33.28PiePlot3D . . . . . . . . . . . . 33.29PiePlotState . . . . . . . . . . . 33.30Plot . . . . . . . . . . . . . . . 33.31PlotOrientation . . . . . . . . . 33.32PlotRenderingInfo . . . . . . . 33.33PlotState . . . . . . . . . . . . 33.34PlotUtilities . . . . . . . . . . . 33.35PolarPlot . . . . . . . . . . . . 33.36RainbowPalette . . . . . . . . . 33.37RingPlot . . . . . . . . . . . . . 33.38SeriesRenderingOrder . . . . . 33.39SpiderWebPlot . . . . . . . . . 33.40ThermometerPlot . . . . . . . . 33.41ValueAxisPlot . . . . . . . . . . 33.42ValueMarker . . . . . . . . . . 33.43WaferMapPlot . . . . . . . . . 33.44XYPlot . . . . . . . . . . . . . 33.45Zoomable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 304 304 304 306 311 312 313 315 316 317 320 321 321 321 321 322 323 324 325 328 328 330 334 335 339 342 342 342 354 356 356 361 361 363 363 363 368 368 370 370 375 382 382 383 383 393 CONTENTS 9 34 Package: org.jfree.chart.plot.dial 34.1 Overview . . . . . . . . . . . . . 34.2 AbstractDialLayer . . . . . . . . 34.3 ArcDialFrame . . . . . . . . . . . 34.4 DialBackground . . . . . . . . . . 34.5 DialCap . . . . . . . . . . . . . . 34.6 DialFrame . . . . . . . . . . . . . 34.7 DialLayer . . . . . . . . . . . . . 34.8 DialLayerChangeEvent . . . . . . 34.9 DialLayerChangeListener . . . . 34.10DialPlot . . . . . . . . . . . . . . 34.11DialPointer . . . . . . . . . . . . 34.12DialPointer.Pin . . . . . . . . . . 34.13DialPointer.Pointer . . . . . . . . 34.14DialScale . . . . . . . . . . . . . 34.15DialTextAnnotation . . . . . . . 34.16DialValueIndicator . . . . . . . . 34.17SimpleDialFrame . . . . . . . . . 34.18StandardDialRange . . . . . . . . 34.19StandardDialScale . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 395 395 395 397 398 399 401 401 402 403 403 406 407 408 409 410 411 414 415 417 35 Package: org.jfree.chart.renderer 35.1 Overview . . . . . . . . . . . . . 35.2 AbstractRenderer . . . . . . . . . 35.3 AreaRendererEndType . . . . . . 35.4 DefaultPolarItemRenderer . . . . 35.5 GrayPaintScale . . . . . . . . . . 35.6 LookupPaintScale . . . . . . . . . 35.7 NotOutlierException . . . . . . . 35.8 Outlier . . . . . . . . . . . . . . . 35.9 OutlierList . . . . . . . . . . . . 35.10OutlierListCollection . . . . . . . 35.11PaintScale . . . . . . . . . . . . . 35.12PolarItemRenderer . . . . . . . . 35.13RendererState . . . . . . . . . . . 35.14WaferMapRenderer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 421 421 421 440 440 441 442 443 443 444 444 444 445 446 446 36 Package: org.jfree.chart.renderer.category 36.1 Overview . . . . . . . . . . . . . . . . . . . 36.2 AbstractCategoryItemRenderer . . . . . . . 36.3 AreaRenderer . . . . . . . . . . . . . . . . . 36.4 BarRenderer . . . . . . . . . . . . . . . . . 36.5 BarRenderer3D . . . . . . . . . . . . . . . . 36.6 BoxAndWhiskerRenderer . . . . . . . . . . 36.7 CategoryItemRenderer . . . . . . . . . . . . 36.8 CategoryItemRendererState . . . . . . . . . 36.9 CategoryStepRenderer . . . . . . . . . . . . 36.10DefaultCategoryItemRenderer . . . . . . . . 36.11GanttRenderer . . . . . . . . . . . . . . . . 36.12GroupedStackedBarRenderer . . . . . . . . 36.13IntervalBarRenderer . . . . . . . . . . . . . 36.14LayeredBarRenderer . . . . . . . . . . . . . 36.15LevelRenderer . . . . . . . . . . . . . . . . . 36.16LineAndShapeRenderer . . . . . . . . . . . 36.17LineRenderer3D . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 447 447 447 451 452 457 459 460 470 471 473 473 474 475 476 477 479 483 CONTENTS 10 36.18MinMaxCategoryRenderer . . . . 36.19ScatterRenderer . . . . . . . . . . 36.20StackedAreaRenderer . . . . . . . 36.21StackedBarRenderer . . . . . . . 36.22StackedBarRenderer3D . . . . . . 36.23StatisticalBarRenderer . . . . . . 36.24StatisticalLineAndShapeRenderer 36.25WaterfallBarRenderer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 485 487 490 490 492 494 495 497 37 Package: org.jfree.chart.renderer.xy 37.1 Overview . . . . . . . . . . . . . . . 37.2 AbstractXYItemRenderer . . . . . . 37.3 CandlestickRenderer . . . . . . . . . 37.4 ClusteredXYBarRenderer . . . . . . 37.5 CyclicXYItemRenderer . . . . . . . . 37.6 DefaultXYItemRenderer . . . . . . . 37.7 DeviationRenderer . . . . . . . . . . 37.8 HighLowRenderer . . . . . . . . . . 37.9 StackedXYAreaRenderer . . . . . . . 37.10StackedXYAreaRenderer2 . . . . . . 37.11StackedXYBarRenderer . . . . . . . 37.12StandardXYItemRenderer . . . . . . 37.13VectorRenderer . . . . . . . . . . . . 37.14WindItemRenderer . . . . . . . . . . 37.15XYAreaRenderer . . . . . . . . . . . 37.16XYBarRenderer . . . . . . . . . . . . 37.17XYBlockRenderer . . . . . . . . . . 37.18XYBoxAndWhiskerRenderer . . . . 37.19XYBubbleRenderer . . . . . . . . . . 37.20XYDifferenceRenderer . . . . . . . . 37.21XYDotRenderer . . . . . . . . . . . 37.22XYErrorRenderer . . . . . . . . . . . 37.23XYItemRenderer . . . . . . . . . . . 37.24XYItemRendererState . . . . . . . . 37.25XYLineAndShapeRenderer . . . . . 37.26XYSplineRenderer . . . . . . . . . . 37.27XYStepRenderer . . . . . . . . . . . 37.28XYStepAreaRenderer . . . . . . . . 37.29YIntervalRenderer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 500 500 500 505 508 509 510 510 512 513 515 516 518 521 523 523 525 527 529 530 532 534 535 537 547 548 554 556 557 558 38 Package: org.jfree.chart.servlet 38.1 Overview . . . . . . . . . . . . 38.2 ChartDeleter . . . . . . . . . . 38.3 DisplayChart . . . . . . . . . . 38.4 ServletUtilities . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 560 560 560 560 560 39 Package: org.jfree.chart.title 39.1 Overview . . . . . . . . . . 39.2 Events . . . . . . . . . . . . 39.3 CompositeTitle . . . . . . . 39.4 DateTitle . . . . . . . . . . 39.5 ImageTitle . . . . . . . . . . 39.6 LegendGraphic . . . . . . . 39.7 LegendItemBlockContainer 39.8 LegendTitle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 562 562 562 562 563 564 564 566 567 . . . . . . . . . . . . . . . . . . . . . . . . CONTENTS 11 39.9 PaintScaleLegend . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 570 39.10TextTitle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 572 39.11Title . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 574 40 Package: org.jfree.chart.urls 40.1 Overview . . . . . . . . . . . . . 40.2 CategoryURLGenerator . . . . . 40.3 CustomPieURLGenerator . . . . 40.4 CustomXYURLGenerator . . . . 40.5 PieURLGenerator . . . . . . . . 40.6 StandardCategoryURLGenerator 40.7 StandardPieURLGenerator . . . 40.8 StandardXYURLGenerator . . . 40.9 StandardXYZURLGenerator . . 40.10TimeSeriesURLGenerator . . . . 40.11URLUtilities . . . . . . . . . . . 40.12XYURLGenerator . . . . . . . . 40.13XYZURLGenerator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 577 577 577 578 579 579 579 581 582 583 583 583 583 584 41 Package: org.jfree.chart.util 585 41.1 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 585 41.2 RelativeDateFormat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 585 42 Package: org.jfree.data 42.1 Introduction . . . . . . . . . . 42.2 ComparableObjectItem . . . 42.3 ComparableObjectSeries . . . 42.4 DataUtilities . . . . . . . . . 42.5 DefaultKeyedValue . . . . . . 42.6 DefaultKeyedValues . . . . . 42.7 DefaultKeyedValues2D . . . . 42.8 DomainInfo . . . . . . . . . . 42.9 DomainOrder . . . . . . . . . 42.10KeyedObject . . . . . . . . . 42.11KeyedObjects . . . . . . . . . 42.12KeyedObjects2D . . . . . . . 42.13KeyedValue . . . . . . . . . . 42.14KeyedValueComparator . . . 42.15KeyedValueComparatorType 42.16KeyedValues . . . . . . . . . 42.17KeyedValues2D . . . . . . . . 42.18KeyToGroupMap . . . . . . . 42.19Range . . . . . . . . . . . . . 42.20RangeInfo . . . . . . . . . . . 42.21RangeType . . . . . . . . . . 42.22UnknownKeyException . . . 42.23Value . . . . . . . . . . . . . 42.24Values . . . . . . . . . . . . . 42.25Values2D . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 588 588 588 589 590 591 592 594 596 596 597 597 599 601 601 601 602 602 603 604 606 606 607 607 607 608 CONTENTS 12 43 Package: org.jfree.data.category 43.1 Introduction . . . . . . . . . . . 43.2 CategoryDataset . . . . . . . . 43.3 CategoryToPieDataset . . . . . 43.4 DefaultCategoryDataset . . . . 43.5 DefaultIntervalCategoryDataset 43.6 IntervalCategoryDataset . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 609 609 609 609 611 613 616 44 Package: org.jfree.data.contour 44.1 Introduction . . . . . . . . . . . 44.2 ContourDataset . . . . . . . . . 44.3 DefaultContourDataset . . . . 44.4 NonGridContourDataset . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 617 617 617 618 618 45 Package: org.jfree.data.function 45.1 Introduction . . . . . . . . . . . 45.2 Function2D . . . . . . . . . . . 45.3 LineFunction2D . . . . . . . . . 45.4 NormalDistributionFunction2D 45.5 PowerFunction2D . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 619 619 619 619 620 621 46 Package: org.jfree.data.gantt 46.1 Introduction . . . . . . . . . 46.2 GanttCategoryDataset . . . 46.3 Task . . . . . . . . . . . . . 46.4 TaskSeries . . . . . . . . . . 46.5 TaskSeriesCollection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 622 622 622 623 624 625 47 Package: org.jfree.data.general 47.1 Introduction . . . . . . . . . . . 47.2 AbstractDataset . . . . . . . . 47.3 AbstractSeriesDataset . . . . . 47.4 CombinationDataset . . . . . . 47.5 CombinedDataset . . . . . . . . 47.6 Dataset . . . . . . . . . . . . . 47.7 DatasetChangeEvent . . . . . . 47.8 DatasetChangeListener . . . . . 47.9 DatasetGroup . . . . . . . . . . 47.10DatasetUtilities . . . . . . . . . 47.11DefaultKeyedValueDataset . . 47.12DefaultKeyedValuesDataset . . 47.13DefaultKeyedValues2DDataset 47.14DefaultPieDataset . . . . . . . 47.15DefaultValueDataset . . . . . . 47.16KeyedValueDataset . . . . . . . 47.17KeyedValuesDataset . . . . . . 47.18KeyedValues2DDataset . . . . 47.19PieDataset . . . . . . . . . . . 47.20Series . . . . . . . . . . . . . . 47.21SeriesChangeEvent . . . . . . . 47.22SeriesChangeListener . . . . . . 47.23SeriesDataset . . . . . . . . . . 47.24SeriesException . . . . . . . . . 47.25SubSeriesDataset . . . . . . . . 47.26ValueDataset . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 628 628 628 629 630 630 630 631 631 631 632 636 636 636 636 638 638 639 639 639 640 642 642 642 643 643 643 . . . . . CONTENTS 13 47.27WaferMapDataset . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 644 48 Package: org.jfree.data.io 645 48.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 645 48.2 CSV . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 645 49 Package: org.jfree.data.jdbc 49.1 Introduction . . . . . . . . . 49.2 JDBCCategoryDataset . . . 49.3 JDBCPieDataset . . . . . . 49.4 JDBCXYDataset . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 646 646 646 647 647 50 Package: org.jfree.data.statistics 50.1 Introduction . . . . . . . . . . . . . . . . 50.2 BoxAndWhiskerCalculator . . . . . . . . 50.3 BoxAndWhiskerCategoryDataset . . . . 50.4 BoxAndWhiskerItem . . . . . . . . . . . 50.5 BoxAndWhiskerXYDataset . . . . . . . 50.6 DefaultBoxAndWhiskerCategoryDataset 50.7 DefaultBoxAndWhiskerXYDataset . . . 50.8 DefaultMultiValueCategoryDataset . . . 50.9 DefaultStatisticalCategoryDataset . . . 50.10HistogramBin . . . . . . . . . . . . . . . 50.11HistogramDataset . . . . . . . . . . . . 50.12HistogramType . . . . . . . . . . . . . . 50.13MeanAndStandardDeviation . . . . . . . 50.14MultiValueCategoryDataset . . . . . . . 50.15Regression . . . . . . . . . . . . . . . . . 50.16SimpleHistogramBin . . . . . . . . . . . 50.17SimpleHistogramDataset . . . . . . . . . 50.18StatisticalCategoryDataset . . . . . . . . 50.19Statistics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 649 649 649 650 651 652 653 656 658 660 662 663 665 666 666 667 668 669 671 671 51 Package: org.jfree.data.time 51.1 Introduction . . . . . . . . . . 51.2 DateRange . . . . . . . . . . 51.3 Day . . . . . . . . . . . . . . 51.4 DynamicTimeSeriesCollection 51.5 FixedMillisecond . . . . . . . 51.6 Hour . . . . . . . . . . . . . . 51.7 Millisecond . . . . . . . . . . 51.8 Minute . . . . . . . . . . . . . 51.9 Month . . . . . . . . . . . . . 51.10MovingAverage . . . . . . . . 51.11Quarter . . . . . . . . . . . . 51.12RegularTimePeriod . . . . . . 51.13Second . . . . . . . . . . . . . 51.14SimpleTimePeriod . . . . . . 51.15TimePeriod . . . . . . . . . . 51.16TimePeriodAnchor . . . . . . 51.17TimePeriodFormatException 51.18TimePeriodValue . . . . . . . 51.19TimePeriodValues . . . . . . 51.20TimePeriodValuesCollection . 51.21TimeSeries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 674 674 674 674 676 678 678 679 680 681 682 683 684 686 687 687 688 688 688 689 691 693 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . CONTENTS 51.22TimeSeriesCollection . 51.23TimeSeriesDataItem . 51.24TimeSeriesTableModel 51.25TimeTableXYDataset 51.26Week . . . . . . . . . . 51.27Year . . . . . . . . . . 14 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 698 701 702 702 704 705 52 Package: org.jfree.data.time.ohlc 52.1 Introduction . . . . . . . . . . . . 52.2 OHLC . . . . . . . . . . . . . . . 52.3 OHLCItem . . . . . . . . . . . . 52.4 OHLCSeries . . . . . . . . . . . . 52.5 OHLCSeriesCollection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 707 707 707 708 709 709 53 Package: org.jfree.data.xml 53.1 Introduction . . . . . . . . 53.2 Usage . . . . . . . . . . . 53.3 CategoryDatasetHandler . 53.4 CategorySeriesHandler . . 53.5 DatasetReader . . . . . . 53.6 DatasetTags . . . . . . . . 53.7 ItemHandler . . . . . . . . 53.8 KeyHandler . . . . . . . . 53.9 PieDatasetHandler . . . . 53.10RootHandler . . . . . . . 53.11ValueHandler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 712 712 712 712 713 713 713 714 714 714 715 715 54 Package: org.jfree.data.xy 54.1 Introduction . . . . . . . . . 54.2 AbstractIntervalXYDataset 54.3 AbstractXYDataset . . . . 54.4 AbstractXYZDataset . . . . 54.5 CategoryTableXYDataset . 54.6 DefaultHighLowDataset . . 54.7 DefaultIntervalXYDataset . 54.8 DefaultOHLCDataset . . . 54.9 DefaultTableXYDataset . . 54.10DefaultWindDataset . . . . 54.11DefaultXYDataset . . . . . 54.12DefaultXYZDataset . . . . 54.13IntervalXYDataset . . . . . 54.14IntervalXYDelegate . . . . . 54.15IntervalXYZDataset . . . . 54.16MatrixSeries . . . . . . . . . 54.17MatrixSeriesCollection . . . 54.18NormalizedMatrixSeries . . 54.19OHLCDataItem . . . . . . . 54.20OHLCDataset . . . . . . . . 54.21TableXYDataset . . . . . . 54.22Vector . . . . . . . . . . . . 54.23VectorDataItem . . . . . . . 54.24VectorSeries . . . . . . . . . 54.25VectorSeriesCollection . . . 54.26VectorXYDataset . . . . . . 54.27WindDataset . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 716 716 716 716 717 717 719 720 723 724 726 728 730 732 733 734 734 735 736 737 738 739 739 740 741 742 744 744 CONTENTS 15 54.28XisSymbolic . . . . . . . . . 54.29XYBarDataset . . . . . . . 54.30XYCoordinate . . . . . . . 54.31XYDataItem . . . . . . . . 54.32XYDataset . . . . . . . . . 54.33XYDatasetTableModel . . . 54.34XYInterval . . . . . . . . . 54.35XYIntervalDataItem . . . . 54.36XYIntervalSeries . . . . . . 54.37XYIntervalSeriesCollection 54.38XYSeries . . . . . . . . . . 54.39XYSeriesCollection . . . . . 54.40XYZDataset . . . . . . . . . 54.41YInterval . . . . . . . . . . 54.42YIntervalDataItem . . . . . 54.43YIntervalSeries . . . . . . . 54.44YIntervalSeriesCollection . 54.45YisSymbolic . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 745 745 747 748 748 750 751 752 753 754 756 759 761 761 762 763 764 765 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 767 767 767 768 768 769 770 771 772 773 773 774 B JCommon B.1 Introduction . . . . . . . . . . . . . B.2 Align . . . . . . . . . . . . . . . . . B.3 GradientPaintTransformer . . . . . B.4 GradientPaintTransformType . . . B.5 PublicCloneable . . . . . . . . . . . B.6 RectangleAnchor . . . . . . . . . . B.7 RectangleEdge . . . . . . . . . . . B.8 RectangleInsets . . . . . . . . . . . B.9 StandardGradientPaintTransformer B.10 TextAnchor . . . . . . . . . . . . . B.11 UnitType . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 775 775 775 776 776 776 777 777 777 779 781 781 A Migration A.1 Introduction . A.2 1.0.8 to 1.0.9 A.3 1.0.7 to 1.0.8 A.4 1.0.6 to 1.0.7 A.5 1.0.5 to 1.0.6 A.6 1.0.4 to 1.0.5 A.7 1.0.3 to 1.0.4 A.8 1.0.2 to 1.0.3 A.9 1.0.1 to 1.0.2 A.10 1.0.0 to 1.0.1 A.11 0.9.x to 1.0.0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . C Configuring IDEs for JFreeChart 783 C.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 783 C.2 Eclipse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 783 C.3 NetBeans . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 787 D The D.1 D.2 D.3 GNU Lesser General Public Licence Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . The Licence . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Frequently Asked Questions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 790 790 790 796 Chapter 1 Introduction 1.1 1.1.1 What is JFreeChart? Overview JFreeChart is a free chart library for the Java(tm) platform. It is designed for use in applications, applets, servlets and JSP. JFreeChart is distributed with complete source code subject to the terms of the GNU Lesser General Public Licence, which permits JFreeChart to be used in proprietary or free software applications (see Appendix D for details). Dual Axis Chart 80 8.0 75 7.5 70 7.0 65 6.5 60 6.0 55 5.5 Value 45 4.5 4.0 40 3.5 35 3.0 30 2.5 25 2.0 20 1.5 15 1.0 10 0.5 5 0.0 0 Secondary 50 5.0 C C C C C C C C at at at at at at at at eg eg eg eg eg eg eg eg or or or y y y y y or or y y or y or or 8 7 6 5 4 3 2 1 Category S1 S2 S3 S4 Figure 1.1: A sample chart Figure 1.1 shows a typical chart created using JFreeChart. Many more examples are shown in later sections of this document. 1.1.2 Features JFreeChart can generate pie charts, bar charts (regular and stacked, with an optional 3D-effect), line charts, scatter plots, time series charts (including moving averages, high-low-open-close charts and candlestick plots), Gantt charts, meter charts (dial, compass and thermometer), symbol charts, wind plots, combination charts and more. Additional features include: 16 CHAPTER 1. INTRODUCTION 17 • data is accessible from any implementation of the defined interfaces; • export to PNG and JPEG image file formats (or you can use Java’s ImageIO library to export to any format supported by ImageIO); • export to any format with a Graphics2D implementation including: – PDF via iText (http://www.lowagie.com/iText/); – SVG via Batik (http://xml.apache.org/batik/); • tool tips; • interactive zooming; • chart mouse events (these can be used for drill-down charts or information pop-ups); • annotations; • HTML image map generation; • works in applications, servlets, JSP (thanks to the Cewolf project1 ) and applets; • distributed with complete source code subject to the terms of the GNU Lesser General Public License (LGPL); JFreeChart is written entirely in Java, and should run on any implementation of the Java 2 platform (JDK 1.3.1 or later). It will also work quite well with free runtimes based on GNU Classpath 0.92 or later.2 1.1.3 Home Page The JFreeChart home page can be found at: http://www.jfree.org/jfreechart/ Here you will find all the latest information about JFreeChart, including sample charts, download links, Javadocs, a discussion forum and more. 1 See 2 See http://cewolf.sourceforge.net for details. http://www.gnu.org/software/classpath/ for details. CHAPTER 1. INTRODUCTION 1.2 18 This Document 1.2.1 Versions Two versions of this document are available: • a free version, the “JFreeChart Installation Guide”, is available from the JFreeChart home page, and contains chapters up to and including the instructions for installing JFreeChart and running the demo; • a premium version, the “JFreeChart Developer Guide”, is available only to those that have paid for it, and includes additional tutorial chapters and reference documentation for the JFreeChart classes. If you wish to purchase the latter version, please visit the following site: http://www.object-refinery.com/jfreechart/guide.html We’d like to thank everyone that has supported JFreeChart in the past by purchasing the JFreeChart Developer Guide! 1.2.2 Disclaimer Please note that I have put in considerable effort to ensure that the information in this document is up-to-date and accurate, but I cannot guarantee that it does not contain errors. You must use this document at your own risk or not use it at all. 1.3 Acknowledgements JFreeChart contains code and ideas from many people. At the risk of missing someone out, I would like to thank the following people for contributing to the project: Eric Alexander, Richard Atkinson, David Basten, David Berry, Chris Boek, Zoheb Borbora, Anthony Boulestreau, Jeremy Bowman, Daniel Bridenbecker, Nicolas Brodu, Jody Brownell, David Browning, Søren Caspersen, Chuanhao Chiu, Brian Cole, Pascal Collet, Martin Cordova, Paolo Cova, Michael Duffy, Don Elliott, Rune Fausk, Jonathan Gabbai, Serge V. Grachov, Daniel Gredler, Hans-Jurgen Greiner, Joao Guilherme Del Valle, Nick Guenther, Aiman Han, Cameron Hayne, Jon Iles, Wolfgang Irler, Sergei Ivanov, Adrian Joubert, Darren Jung, Xun Kang, Bill Kelemen, Norbert Kiesel, Gideon Krause, Pierre-Marie Le Biot, Arnaud Lelievre, Wolfgang Lenhard, David Li, Yan Liu, Tin Luu, Craig MacFarlane, Achilleus Mantzios, Thomas Meier, Aaron Metzger, Jim Moore, Jonathan Nash, Barak Naveh, David M. O’Donnell, Krzysztof Paz, Tomer Peretz, Xavier Poinsard, Andrzej Porebski, Luke Quinane, Viktor Rajewski, Eduardo Ramalho, Michael Rauch, Cameron Riley, Klaus Rheinwald, Dan Rivett, Scott Sams, Michel Santos, Thierry Saura, Andreas Schneider, Jean-Luc Schwab, Bryan Scott, Tobias Self, Mofeed Shahin, Pady Srinivasan, Greg Steckman, Roger Studner, Gerald Struck, Irv Thomae, Eric Thomas, Rich Unger, Daniel van Enckevort, Laurence Vanhelsuwé, Sylvain Vieujot, Jelai Wang, Mark Watson, Alex Weber, Richard West, Matthew Wright, Benoit Xhenseval, Christian W. Zuckschwerdt, Hari and Sam (oldman). 1.4 Comments and Suggestions If you have any comments or suggestions regarding this document, please send e-mail to: david.gilbert@object-refinery.com Chapter 2 Sample Charts 2.1 Introduction This section shows some sample charts created using JFreeChart. It is intended to give a reasonable overview of the types of charts that JFreeChart can generate. For other examples, please run the demo application included in the JFreeChart distribution: java -jar jfreechart-1.0.9-demo.jar The complete source code for the demo application is available to purchasers of the JFreeChart Developer Guide.1 2.2 Pie Charts JFreeChart can create pie charts using any data that conforms to the PieDataset interface. Figure 2.1 shows a simple pie chart. Pie Chart Demo 1 Six One Five Four Two Three One Two Three Four Five Six Figure 2.1: A simple pie chart (see PieChartDemo1.java) 1 See http://www.object-refinery.com/jfreechart/guide.html for details. 19 CHAPTER 2. SAMPLE CHARTS 20 Individual pie sections can be “exploded”, as shown in figure 2.2. Pie Chart Demo 2 Six (15% percent) One (34% percent) Five (9% percent) Four (14% percent) Two (8% percent) Three (21% percent) One Two Three Four Five Six Figure 2.2: A pie chart with an “exploded” section (see PieChartDemo2.java) You can also display pie charts with a 3D effect, as shown in figure 2.3. Pie Chart 3D Demo 1 C/C++ Visual Basic PHP Java Perl Java Visual Basic C/C++ PHP Perl Figure 2.3: A pie chart drawn with a 3D effect (see PieChart3DDemo1.java) At the current time it is not possible to explode sections of the 3D pie chart. CHAPTER 2. SAMPLE CHARTS 2.3 21 Bar Charts A range of bar charts can be created with JFreeChart, using any data that conforms to the CategoryDataset interface. Figure 2.4 shows a bar chart with a vertical orientation. Bar Chart Demo 1 8 7 6 Value 5 4 3 2 1 0 Ca teg ory 1 Ca teg ory 2 Ca teg ory 3 Ca teg ory 4 Ca teg ory 5 Category First Second Third Figure 2.4: A vertical bar chart (see BarChartDemo1.java) Bar charts can be displayed with a 3D effect as shown in figure 2.5. 3D Bar Chart Demo 17.5 15.0 12.5 10.0 Value 7.5 5.0 2.5 0.0 -2.5 -5.0 -7.5 -10.0 -12.5 Ca teg ory 1 Ca teg ory 2 Ca teg ory 3 Ca teg ory 4 Category Series 1 Series 2 Series 3 Series 4 Series 5 Series 6 Series 7 Series 8 Series 9 Figure 2.5: A bar chart with 3D effect (see BarChart3DDemo1.java) CHAPTER 2. SAMPLE CHARTS 22 Another variation, the waterfall chart, is shown in figure 2.6. Product Cost Breakdown $3.51 30 $4.71 Cost Per Unit 25 $8.66 20 $32.64 15 10 $15.76 5 0 Labour Administration Marketing Distribution Total Expense Expense Category Figure 2.6: A waterfall chart (see WaterfallChartDemo1.java) Bar charts can also be generated from time series data—for example, see figure 2.7: State Executions - USA Source: http://www.amnestyusa.org/abolish/listbyyear.do 100 90 Number of People 80 70 60 50 40 30 20 10 0 1976 1978 1980 1982 1984 1986 1988 1990 1992 1994 1996 1998 2000 2002 2004 Year Executions Figure 2.7: An XY bar chart (see XYBarChartDemo1.java) CHAPTER 2. SAMPLE CHARTS 2.4 23 Line Chart The line chart can be generated using the same CategoryDataset that is used for the bar charts— figure 2.8 shows an example. Java Standard Class Library Number of Classes By Release 3000 2800 2600 2400 Class Count 2200 2000 1800 1600 1400 1200 1000 800 600 400 200 0 JDK 1.0 JDK 1.1 SDK 1.2 SDK 1.3 SDK 1.4 Release Source: Java In A Nutshell (4th Edition) by David Flanagan (O'Reilly) Figure 2.8: A line chart (see LineChartDemo1.java) CHAPTER 2. SAMPLE CHARTS 2.5 24 XY Plots A third type of dataset, the XYDataset, is used to generate a range of chart types. The standard XY plot has numerical x and y axes. By default, lines are drawn between each data point—see figure 2.9. Line Chart Demo 4 2.00 1.75 1.50 1.25 1.00 0.75 0.50 Y 0.25 0.00 -0.25 -0.50 -0.75 -1.00 -1.25 -1.50 -1.75 -2.00 -10 -9 -8 -7 -6 -5 -4 -3 -2 -1 0 1 2 3 4 5 6 7 8 9 X y = cosine(x) y = 2*sine(x) Figure 2.9: A line chart (see LineChartDemo4.java) Scatter plots can be drawn by drawing a shape at each data point, rather than connecting the points with lines—an example is shown in figure 2.10. Scatter Plot Demo 1 900 800 700 600 500 400 300 200 Y 100 0 -100 -200 -300 -400 -500 -600 -700 -800 -100 -75 -50 -25 0 25 50 75 X Sample 0 Sample 1 Sample 2 Sample 3 Figure 2.10: A scatter plot (see ScatterPlotDemo1.java) 100 CHAPTER 2. SAMPLE CHARTS 2.6 25 Time Series Charts JFreeChart supports time series charts, as shown in figure 2.11. Legal & General Unit Trust Prices 185 180 175 170 165 160 Price Per Unit 155 150 145 140 135 130 125 120 115 110 105 100 Mar-2001 May-2001 Jul-2001 Sep-2001 Nov-2001 Jan-2002 Mar-2002 May-2002 Jul-2002 Date L&G European Index Trust L&G UK Index Trust Figure 2.11: A time series chart (see TimeSeriesDemo1.java) It is straightforward to add a moving average line to a time series chart—see figure 2.12 for an example. Time Series Demo 8 1.68 1.67 1.66 1.65 1.64 Value 1.63 1.62 1.61 1.60 1.59 1.58 1.57 1.56 Jan-2001 Mar-2001 May-2001 Jul-2001 Sep-2001 Nov-2001 Date EUR/GBP 30 day moving average Figure 2.12: A time series chart with a moving average (see TimeSeriesDemo8.java) CHAPTER 2. SAMPLE CHARTS 26 Using an OHLCDataset (an extension of XYDataset) you can display high-low-open-close data, see figure 2.13 for an example. OHLC Demo 2 65 60 55 50 45 Value 40 35 30 25 20 15 10 5 0 7-Jan 14-Jan 21-Jan 28-Jan 4-Feb 11-Feb 18-Feb Time Series 1 Series 1-MAVG Figure 2.13: A high-low-open-close chart (see HighLowChartDemo2.java) 2.7 Histograms Histograms can be generated using an IntervalXYDataset (another extension of XYDataset), see figure 2.14 for an example. Histogram Demo 32.5 30.0 27.5 25.0 22.5 20.0 17.5 15.0 12.5 10.0 7.5 5.0 2.5 0.0 2.0 2.5 3.0 3.5 4.0 4.5 5.0 5.5 H1 6.0 6.5 7.0 7.5 8.0 8.5 9.0 9.5 H2 Figure 2.14: A histogram (see HistogramDemo1.java) 10.0 CHAPTER 2. SAMPLE CHARTS 2.8 27 Area Charts You can generate an area chart for data in a CategoryDataset or an XYDataset. Figure 2.15 shows an example. XY Area Chart Demo 800 700 600 500 400 300 Range (Y) 200 100 0 -100 -200 -300 -400 -500 -600 Test -700 -800 1.0 1.5 2.0 2.5 3.0 3.5 4.0 4.5 5.0 5.5 6.0 6.5 7.0 7.5 8.0 Domain (X) Random 1 Random 2 Figure 2.15: An area chart (see XYAreaChartDemo1.java) JFreeChart also supports the creation of stacked area charts as shown in figure 2.16. Stacked XY Area Chart Demo 1 32.5 30.0 27.5 25.0 22.5 Y Value 20.0 17.5 15.0 12.5 10.0 7.5 5.0 2.5 0.0 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 X Value Series 1 Series 2 Figure 2.16: A stacked area chart (see StackedXYAreaChartDemo1.java) 2.9 Difference Chart A difference chart highlights the difference between two series (see figure 2.17). A second example, shown in figure 2.18 shows how a date axis can be used for the range values. CHAPTER 2. SAMPLE CHARTS 28 Difference Chart Demo 1 3.0 2.5 2.0 1.5 Value 1.0 0.5 0.0 -0.5 -1.0 -1.5 -2.0 -2.5 Aug-2006 Sep-2006 Oct-2006 Nov-2006 Dec-2006 Jan-2007 Feb-2007 Time Random 1 Random 2 Figure 2.17: A difference chart (see DifferenceChartDemo1.java) Daylight Hours - London, UK Data source: http://www.sunrisesunset.com/ 22:00 20:00 18:00 Time 16:00 14:00 12:00 10:00 08:00 06:00 04:00 British Summer Time Feb-2004 Apr-2004 Jun-2004 Aug-2004 Oct-2004 Dec-2004 Time Sunrise Sunset Figure 2.18: A difference chart with times on the range axis (see DifferenceChartDemo2.java) CHAPTER 2. SAMPLE CHARTS 2.10 29 Step Chart A step chart displays numerical data as a sequence of “steps”—an example is shown in figure 2.19. XYStepRenderer Demo 1 9.0 8.5 8.0 7.5 7.0 6.5 6.0 Y 5.5 5.0 4.5 4.0 3.5 3.0 2.5 2.0 1.5 1.0 0.5 0.0 1.0 1.5 2.0 2.5 3.0 3.5 4.0 4.5 5.0 5.5 X Series 1 Series 2 Figure 2.19: A step chart (see XYStepRendererDemo1.java) Step charts are generated from data in an XYDataset. 6.0 CHAPTER 2. SAMPLE CHARTS 2.11 30 Gantt Chart Gantt charts can be generated using data from an IntervalCategoryDataset, as shown in figure 2.20. Gantt Chart Demo Date May-2001 Jul-2001 Sep-2001 Nov-2001 Write Proposal Obtain Approval Requirements Analysis Design Phase Task Design Signoff Alpha Implementation Design Review Revised Design Signoff Beta Implementation Testing Final Implementation Signoff Scheduled Actual Figure 2.20: A Gantt chart (see GanttChartDemo1.java) Another example, showing subtasks and progress indicators, is shown in figure 2.21. Gantt Chart Demo Date May-2001 Jul-2001 Sep-2001 Nov-2001 Write Proposal Obtain Approval Requirements Analysis Design Phase Task Design Signoff Alpha Implementation Design Review Revised Design Signoff Beta Implementation Testing Final Implementation Signoff Scheduled Figure 2.21: A Gantt chart with progress indicators (see GanttChartDemo2.java) CHAPTER 2. SAMPLE CHARTS 2.12 31 Multiple Axis Charts JFreeChart has support for charts with multiple axes. Figure 2.22 shows a price-volume chart that demonstrates this feature. Eurodollar Futures Contract (MAR03) 750,000 98.50 98.25 700,000 98.00 650,000 97.75 600,000 97.50 550,000 97.25 500,000 96.75 450,000 96.50 400,000 96.25 350,000 96.00 Volume Price 97.00 300,000 95.75 250,000 95.50 95.25 200,000 95.00 150,000 94.75 100,000 94.50 50,000 94.25 Jan-2002 Mar-2002 May-2002 Jul-2002 Sep-2002 0 Nov-2002 Date Price Volume Figure 2.22: A price-volume chart (see PriceVolumeDemo1.java) This feature is supported by the CategoryPlot and XYPlot classes. Figure 2.23 shows an example with four range axes. Multiple Axis Demo 1 Four datasets and four range axes. 110 1,300 Range Axis 2 1,000 950 27.5 100 11,000 25.0 95 10,000 22.5 9,000 90 8,000 85 7,000 80 6,000 75 5,000 900 70 850 65 800 60 4,000 3,000 11:00 11:30 12:00 12:30 13:00 13:30 20.0 17.5 15.0 12.5 Range Axis 4 1,050 30.0 12,000 Range Axis 3 1,100 Primary Range Axis 1,200 1,150 13,000 105 1,250 10.0 7.5 2,000 5.0 1,000 2.5 0 0.0 14:00 Time of Day Series 1 Series 2 Series 3 Series 4 Figure 2.23: A chart with multiple axes (see MultipleAxisDemo1.java) CHAPTER 2. SAMPLE CHARTS 2.13 32 Combined and Overlaid Charts JFreeChart supports combined and overlaid charts. Figure 2.24 shows a line chart overlaid on top of a bar chart. Freshmeat Software Projects By Programming Language As at 5 March 2003 5000 100% 4500 90% 4000 80% 70% SQL Unix Shell PHP C# 10% 0 Ruby 20% 500 Python 30% 1000 Java 40% 1500 C++ 50% 2000 Perl 60% 2500 C 3000 Percent Projects 3500 0% Language Languages Cumulative Figure 2.24: An overlaid chart (see ParetoChartDemo1.java) It is possible to combine several charts that share a common domain axis, as shown in figure 2.25. Combined Domain Category Plot Demo 8 7 Value 6 5 4 3 2 1 0 Value 15 10 5 0 Type 1 Type 2 Type 3 Type 4 Type 5 Type 6 Type 7 Type 8 Category First Second Third Fourth Figure 2.25: A chart with a combined domain (see CombinedCategoryPlotDemo1.java) In a similar way, JFreeChart can combine several charts that share a common range axis, see figure 2.26. CHAPTER 2. SAMPLE CHARTS 33 Combined (Range) XY Plot 18,000 17,000 16,000 15,000 14,000 13,000 12,000 Value 11,000 10,000 9,000 8,000 7,000 6,000 5,000 4,000 3,000 2,000 1,000 0 7-Mar 14-Mar 7-Mar Date 14-Mar Date Series 1 Series 2 Figure 2.26: A chart with a combined range (see CombinedXYPlotDemo2.java) 2.14 Future Development JFreeChart is free software,2 so anyone can extend it and add new features to it. Already, more than 80 developers from around the world have contributed code back to the JFreeChart project. It is likely that many more chart types will be developed in the future as developers modify JFreeChart to meet their requirements. Check the JFreeChart home page regularly for announcements and other updates: http://www.jfree.org/jfreechart/ And if you would like to contribute code to the project, please join in... 2 See http://www.fsf.org Chapter 3 Downloading and Installing JFreeChart 3.1 Introduction This section contains instructions for downloading, unpacking, and (optionally) recompiling JFreeChart. Also included are instructions for running the JFreeChart demonstration application, and generating the Javadoc HTML files from the JFreeChart source code. 3.2 Download You can download the latest version of JFreeChart from: http://www.jfree.org/jfreechart/download/ There are two versions of the JFreeChart download: File: Description: jfreechart-1.0.9.tar.gz jfreechart-1.0.9.zip JFreeChart for Linux/Unix. JFreeChart for Windows. The two files contain the same source code. The main difference is that all the text files in the zip download have been recoded to have both carriage return and line-feed characters at the end of each line. JFreeChart uses the JCommon class library (currently version 1.0.12). The JCommon runtime jar file is included in the JFreeChart download, but if you require the source code (recommended) then you should also download JCommon from: http://www.jfree.org/jcommon/ 3.3 Unpacking the Files After downloading JFreeChart, you need to unpack the files. You should move the download file to a convenient directory—when you unpack JFreeChart, a new subdirectory (jfreechart-1.0.9) will be created in the same location as the zip or tar.gz archive file. 3.3.1 Unpacking on Linux/Unix To extract the files from the download on Linux/Unix, enter the following command: 34 CHAPTER 3. DOWNLOADING AND INSTALLING JFREECHART 35 tar xvzf jfreechart-1.0.9.tar.gz This will extract all the source, run-time and documentation files for JFreeChart into a new directory called jfreechart-1.0.9. 3.3.2 Unpacking on Windows To extract the files from the download on Windows, you can use the jar utility. Enter the following command: jar -xvf jfreechart-1.0.9.zip This will extract all the source, run-time and documentation files for JFreeChart into a new directory called jfreechart-1.0.9. 3.3.3 The Files The top-level directory (jfreechart-1.0.9) contains the files and directories listed in the following table: File/Directory: Description: README.txt NEWS ChangeLog ant Important information - read this first! Project news. A detailed log of changes made to JFreeChart. A directory containing an Ant build.xml script. You can use this script to rebuild JFreeChart from the source code included in the distribution. A directory containing several Checkstyle property files. These define the coding conventions used in the JFreeChart source code. A directory containing source files for classes that are not part of the standard JFreeChart API (yet). We would appreciate feedback on this code. Please note that the API for these classes is subject to change. A directory containing the JFreeChart jar file, and other libraries used by JFreeChart. A directory containing the source code for JFreeChart. A directory containing the source code for the experimental SWT code. Please note that the API for these classes is subject to change. A directory containing the source code for the JFreeChart unit tests. A runnable jar file containing demo applications. The JFreeChart licence (GNU LGPL). checkstyle experimental lib source swt tests jfreechart-1.0.9-demo.jar licence-LGPL.txt You should spend some time familiarising yourself with the files included in the download. In particular, you should always read the README.txt file. 3.4 Running the Demonstration Applications A demonstration application is included in the distribution that shows a wide range of charts that can be generated with JFreeChart . To run the demo, type the following command: java -jar jfreechart-1.0.9-demo.jar The source code for the demo application is not included in the JFreeChart distribution, but is available to download separately when you purchase the JFreeChart Developer Guide.1 1 If you have purchased the guide and you want to download the demo source code, look for the file jfreechart-1.0.9-demos.zip on the download page for the JFreeChart Developer Guide. CHAPTER 3. DOWNLOADING AND INSTALLING JFREECHART 3.5 36 Configuring JFreeChart for use in IDEs If, like most developers, you use an integrated development environment (IDE) such as Eclipse or NetBeans for your Java development work, you’ll want to configure JFreeChart within that IDE. The procedure for this is IDE-specific—refer to Appendix C for more details. 3.6 Compiling the Source To recompile the JFreeChart classes, you can use the Ant build.xml file included in the distribution. Change to the ant directory and type: ant compile This will recompile all the necessary source files and recreate the JFreeChart run-time jar file. To run the script requires that you have Ant 1.5.1 (or later) installed on your system, to find out more about Ant visit: http://ant.apache.org/ It is possible to recompile JFreeChart without using Ant, but there are one or two “gotchas” that you have to take special care to avoid: • some JFreeChart classes (particularly resource bundles) are not referenced directly in the code, and some compilers omit to compile them—this results in runtime errors or problems due to missing class files; • if you create your own JFreeChart jar file, you need to be sure to include the non-Java files (resource bundle .properties files, gorilla.jpg, etc.). In the end, it’s simpler to learn Ant and use the script included in the JFreeChart distribution. 3.7 Generating the Javadoc Documentation The JFreeChart source code contains extensive Javadoc comments. You can use the javadoc tool to generate HTML documentation files directly from the source code. To generate the documentation, use the javadoc target in the Ant build.xml script: ant javadoc This will create a javadoc directory containing all the Javadoc HTML files, inside the main jfreechart-1.0.9 directory. Chapter 4 Using JFreeChart 4.1 Overview This section presents a simple introduction to JFreeChart, intended for new users of JFreeChart. 4.2 4.2.1 Creating Your First Chart Overview Creating charts with JFreeChart is a three step process. You need to: • create a dataset containing the data to be displayed in the chart; • create a JFreeChart object that will be responsible for drawing the chart; • draw the chart to some output target (often, but not always, a panel on the screen); To illustrate the process, we describe a sample application (First.java) that produces the pie chart shown in figure 4.1. Figure 4.1: A pie chart created using First.java Each of the three steps outlined above is described, along with sample code, in the following sections. 4.2.2 The Data Step one requires us to create a dataset for our chart. This can be done easily using the DefaultPieDataset class, as follows: 37 CHAPTER 4. USING JFREECHART 38 // create a dataset... DefaultPieDataset dataset = new DefaultPieDataset(); dataset.setValue("Category 1", 43.2); dataset.setValue("Category 2", 27.9); dataset.setValue("Category 3", 79.5); Note that JFreeChart can create pie charts using data from any class that implements the PieDataset interface. The DefaultPieDataset class (used above) provides a convenient implementation of this interface, but you are free to develop an alternative dataset implementation if you want to.1 4.2.3 Creating a Pie Chart Step two concerns how we will present the dataset created in the previous section. We need to create a JFreeChart object that can draw a chart using the data from our pie dataset. We will use the ChartFactory class, as follows: // create a chart... JFreeChart chart = ChartFactory.createPieChart( "Sample Pie Chart", dataset, true, // legend? true, // tooltips? false // URLs? ); Notice how we have passed a reference to the dataset to the factory method. JFreeChart keeps a reference to this dataset so that it can obtain data later on when it is drawing the chart. The chart that we have created uses default settings for most attributes. There are many ways to customise the appearance of charts created with JFreeChart, but in this example we will just accept the defaults. 4.2.4 Displaying the Chart The final step is to display the chart somewhere. JFreeChart is very flexible about where it draws charts, thanks to its use of the Graphics2D class. For now, let’s display the chart in a frame on the screen. The ChartFrame class contains the machinery (a ChartPanel) required to display charts: // create and display a frame... ChartFrame frame = new ChartFrame("Test", chart); frame.pack(); frame.setVisible(true); And that’s all there is to it... 4.2.5 The Complete Program Here is the complete program, so that you can see which packages you need to import and the order of the code fragments given in the preceding sections: import import import import org.jfree.chart.ChartFactory; org.jfree.chart.ChartFrame; org.jfree.chart.JFreeChart; org.jfree.data.general.DefaultPieDataset; public class First { /** * The starting point for the demo. * * @param args ignored. */ public static void main(String[] args) { 1 This is similar in concept to the way that Swing’s JTable class obtains data via the TableModel interface. In fact, this was the inspiration for using interfaces to define the datasets for JFreeChart. CHAPTER 4. USING JFREECHART 39 // create a dataset... DefaultPieDataset dataset = new DefaultPieDataset(); dataset.setValue("Category 1", 43.2); dataset.setValue("Category 2", 27.9); dataset.setValue("Category 3", 79.5); // create a chart... JFreeChart chart = ChartFactory.createPieChart( "Sample Pie Chart", dataset, true, // legend? true, // tooltips? false // URLs? ); // create and display a frame... ChartFrame frame = new ChartFrame("First", chart); frame.pack(); frame.setVisible(true); } } Hopefully this has convinced you that it is not difficult to create and display charts with JFreeChart. Of course, there is much more to learn... Chapter 5 Pie Charts 5.1 Introduction This chapter provides information about using some of the standard features of the pie charts in JFreeChart, including: • controlling the color and outline of pie sections; • handling of null and zero values; • pie section labels (customising the text, altering the space allocated); • “exploded” sections; • multiple pie charts. • displaying charts with a 3D effect; In addition to this chapter, you should refer to the PiePlot reference documentation in section 33.27. 5.2 Creating a Simple Pie Chart A step-by-step guide to creating a simple pie chart is included in the previous chapter 4. 5.3 Section Colours Default fill colours for the pie sections are allocated automatically1 the first time a plot is rendered. If you don’t like the default colours, you can set them yourself using the setSectionPaint(Comparable, Paint) method. For example: PiePlot plot = (PiePlot) chart.getPlot(); plot.setSectionPaint("Section A", new Color(200, 255, 255)); plot.setSectionPaint("Section B", new Color(200, 200, 255)); A demo that uses custom colours (PieChartDemo2.java) is included in the JFreeChart demo collection. In addition to the per-series section colour attributes, there is also a base or default setting—for more information, refer to the documentation for the PiePlot class (section 33.27). 1 Inside the lookupSectionPaint(Comparable, boolean) method of the PiePlot class. 40 CHAPTER 5. PIE CHARTS 5.4 41 Section Outlines Section outlines are drawn, by default, as a thin grey line around each pie section. The PiePlot class provides options to: • switch off the outlines completely; • change the outlines for all sections by changing the default values; • control the outline for particular pie sections independently; 5.4.1 Outline Visibility To switch off the section outlines completely, use the following code: PiePlot plot = (PiePlot) chart.getPlot(); plot.setSectionOutlinesVisible(false); At any time, you can make the outlines visible again using: plot.setSectionOutlinesVisible(true); Calls to this method trigger a PlotChangeEvent, which will cause the chart to be repainted immediately if it is displayed in a ChartPanel. 5.4.2 Outline Appearance When outlines are visible, you can change the colour and style of the outline for all pie sections (using the base settings) or individual pie sections (using the per series settings). At the base layer, a default setting is defined—this is used when no higher level settings have been made. You can change the base settings with these methods in the PiePlot class: public void setBaseSectionOutlinePaint(Paint paint); public void setBaseSectionOutlineStroke(Stroke stroke); Sometimes, you may prefer to set the outline paint and stroke on a “per series” basis, perhaps to highlight a particular section in the chart. For this, you can use the series layer settings, defined via these methods: public void setSectionOutlinePaint(Comparable key, Paint paint); public void setSectionOutlineStroke(Comparable key, Stroke stroke); The first argument for each method is the section key from the dataset. If you set the value for a section to null, the base layer setting will be used instead. 5.5 Null, Zero and Negative Values A PieDataset can contain null, zero or negative values which are awkward or impossible to display in a pie chart. Some special handling is built into the PiePlot class for these. If a zero value is found in the dataset, the PiePlot class, by default, will place a label at the position where the pie section would be displayed if it had a positive value and will also add an item to the chart’s legend. If you prefer zero values to be ignored, you can set a flag for this, as follows: PiePlot plot = (PiePlot) chart.getPlot(); plot.setIgnoreZeroValues(true); A similar approach is taken for null values, which represent a missing or unknown value in the dataset. The default handling is the same as for zero values, and if you prefer null values to be ignored, you can set a flag as follows: PiePlot plot = (PiePlot) chart.getPlot(); plot.setIgnoreNullValues(true); There does not seem to be a sensible way to represent negative values in a pie chart, and JFreeChart will always ignore them. CHAPTER 5. PIE CHARTS 5.6 42 Section and Legend Labels The text used for the section labels, both on the chart and in the chart’s legend, is fully customisable. Default label generators are installed automatically, but if you need to you can change these with the following methods: public void setLabelGenerator(PieSectionLabelGenerator generator); public void setLegendLabelGenerator(PieSectionLabelGenerator generator); The StandardPieSectionLabelGenerator class is typically used as the generator, and provides enough flexibility to handle most custom labelling requirements (but if not, you are free two write your own class that implements the PieSectionLabelGenerator interface). The generator works by using Java’s MessageFormat class to construct labels by substituting values that are derived from the dataset—see table 5.1 for the available substitutions. Key: Value: {0} {1} {2} The section key as a String. The section value. The section value as a percentage of the total of all values in the dataset. Figure 5.1: StandardPieSectionLabelGenerator substitutions By way of example, suppose you have a PieDataset containing the following values: Section Key: Section Value: S1 S2 S3 S4 3.0 5.0 null 2.0 Figure 5.2: A sample dataset ...then the following format strings would generate the labels shown: Format String: Section: Generated Label: {0} {0} has value {1} {0} ({2} percent) {0} = {1} 0 1 0 2 S1 S2 has value 5.0 S1 (30 percent) S3 = null Figure 5.3: Format string examples The PieChartDemo2.java application (included in the JFreeChart demo collection) shows a custom label generator in use. 5.7 Exploded Sections The PiePlot class supports the display of “exploded” sections, in which a pie section is offset from the centre of the chart to highlight it. For example, the PieChartDemo2.java application creates the chart shown in figure 5.6. The amount by which a section is offset from the chart is specified as a percentage of the radius of the pie chart, for example 0.30 (30 percent) is used in the example. PiePlot plot = (PiePlot) chart.getPlot(); plot.setExplodePercent("Section A", 0.30); To make space for the sections that are offset from the centre of the pie chart, the radius of the main pie is reduced, so a pie chart with exploded sections will appear smaller than a pie chart with no exploded sections. CHAPTER 5. PIE CHARTS 43 Figure 5.4: A pie chart with an “exploded” section 5.8 3D Pie Charts JFreeChart includes a PiePlot3D class that adds a pseudo-3D effect to pie charts—for example, see figure 5.5. PiePlot3D is a subclass of PiePlot, so you can just substitute it when you create your pie chart. Or if you construct your pie charts using the ChartFactory class, it is sufficient to call the createPieChart3D() method instead of the createPieChart() method. Figure 5.5: A 3D pie chart There are some limitations with this class: • exploded sections are not supported; • it is not possible to set the angle of “rotation” for the 3D effect—if the plot is wider than it is tall, the chart usually looks good, but if the plot is taller than it is wide, the 3D effect is a little distorted. Some demo applications (PieChart3DDemo1-3.java) are included in the JFreeChart demo collection. 5.9 Multiple Pie Charts As a convenience, the MultiplePiePlot class enables you to create a single chart that displays multiple pie plots using data from a CategoryDataset. An example is shown in figure 5.6. The individual pie charts are created by “rubber stamping” a single pie chart multiple times. For each rendering of the pie chart, a new PieDataset is extracted from the next row (or column) of the CategoryDataset. CHAPTER 5. PIE CHARTS 44 Figure 5.6: A chart using MultiplePiePlot A number of demos (MultiplePieChartDemo1-4.java) are included in the JFreeChart demo collection. Chapter 6 Bar Charts 6.1 Introduction This chapter provides an introduction to creating bar charts with JFreeChart. We begin with a very simple bar chart, then go on to describe some of the many options that JFreeChart provides for customising the charts. After covering the standard bar chart and its options, we’ll move on to some more complex bar chart variants: • stacked bar charts; • bar charts for time series data; • histograms. By the end of this chapter, you should have a good overview of the features that JFreeChart supports for bar chart creation. 6.2 6.2.1 A Bar Chart Overview Bar charts are used to provide a visual representation of tabular data. For example, consider the following table, which contains a simple set of data in two rows and three columns: Row 1: Row 2: Column 1: Column 2: Column 3: 1.0 2.0 5.0 3.0 3.0 2.0 Figure 6.1: Sample data In JFreeChart, this table is referred to as a dataset, each column heading is a category, and each row in the table is a series. Each row heading is a series name (or series key). A bar chart that presents this data is shown in figure 6.2. You can see in the sample chart that JFreeChart groups the items from each column (category) together, and uses colours to highlight the data from each row (series). The chart’s legend provides the link between the bar colours and the series name/key. 6.2.2 Creating a Dataset The first step in creating a bar chart is to create an appropriate dataset. The set of methods that JFreeChart uses to access the tabular data for a bar chart is defined by the CategoryDataset interface. 45 CHAPTER 6. BAR CHARTS 46 Figure 6.2: A bar chart (see BarExample1.java) This interface defines a read-only interface to the dataset, because that is all that JFreeChart requires to draw charts. A dataset can, but is not required to, provide methods to update the dataset. A convenient class that implements this interface is the DefaultCategoryDataset class. Here is how you might create a dataset for the values given in table 6.1: DefaultCategoryDataset dataset = new DefaultCategoryDataset(); dataset.addValue(1.0, "Row 1", "Column 1"); dataset.addValue(5.0, "Row 1", "Column 2"); dataset.addValue(3.0, "Row 1", "Column 3"); dataset.addValue(2.0, "Row 2", "Column 1"); dataset.addValue(3.0, "Row 2", "Column 2"); dataset.addValue(2.0, "Row 2", "Column 3"); 6.2.3 Creating a Bar Chart The next step is to create a JFreeChart instance that draws a bar chart for this example dataset. Taking a short-cut, we use the ChartFactory class to create the JFreeChart instance: JFreeChart chart = ChartFactory.createBarChart( "Bar Chart Demo", // chart title "Category", // domain axis label "Value", // range axis label dataset, // data PlotOrientation.VERTICAL, // orientation true, // include legend true, // tooltips? false // URLs? ); Most of the arguments to the createBarChart() method are obvious, but a few of them demand further explanation: • the plot orientation can be either horizontal or vertical (for bar charts, this corresponds to the way the bars are drawn, horizontally or vertically); • the tooltips flag controls whether or not a tool tip generator is added to the chart—in this example, we’ve set this flag to true so that we’ll see tool tips when we display the chart in a Swing application; CHAPTER 6. BAR CHARTS 47 • the URLs flag is only relevant when creating drill-down reports using HTML image maps, so we set it to cffalse here. After we’ve completed this first bar chart example, we’ll come back and take a closer look at what the ChartFactory class is doing “behind the scenes” here. 6.2.4 Displaying the Chart To complete our first bar chart example, we pass the JFreeChart instance to a ChartPanel and display it in a simple Swing application. The full source code for this example is listed here: /* ---------------* BarExample1.java * ---------------* (C) Copyright 2006, by Object Refinery Limited. * */ package tutorial; import java.awt.Dimension; /** * A simple demonstration application showing how to create a bar chart. */ public class BarExample1 extends ApplicationFrame { /** * Creates a new demo instance. * * @param title the frame title. */ public BarExample1(String title) { super(title); DefaultCategoryDataset dataset = new DefaultCategoryDataset(); dataset.addValue(1.0, "Row 1", "Column 1"); dataset.addValue(5.0, "Row 1", "Column 2"); dataset.addValue(3.0, "Row 1", "Column 3"); dataset.addValue(2.0, "Row 2", "Column 1"); dataset.addValue(3.0, "Row 2", "Column 2"); dataset.addValue(2.0, "Row 2", "Column 3"); JFreeChart chart = ChartFactory.createBarChart( "Bar Chart Demo", // chart title "Category", // domain axis label "Value", // range axis label dataset, // data PlotOrientation.VERTICAL, // orientation true, // include legend true, // tooltips? false // URLs? ); ChartPanel chartPanel = new ChartPanel(chart, false); chartPanel.setPreferredSize(new Dimension(500, 270)); setContentPane(chartPanel); } /** * Starting point for the demonstration application. * * @param args ignored. */ public static void main(String[] args) { BarExample1 demo = new BarExample1("Bar Demo 1"); demo.pack(); RefineryUtilities.centerFrameOnScreen(demo); demo.setVisible(true); } CHAPTER 6. BAR CHARTS 48 } If you compile and run this example, you should see a frame containing the chart in figure 6.2. 6.3 The ChartFactory Class In our first example, the ChartFactory class is used to piece together a JFreeChart instance that renders a bar chart. Here we take a closer look at how this is done, so we can see a little more of the underlying structure of our bar chart. Understanding this structure is key to being able customise the appearance of the chart. Here are the important parts of the code from the createBarChart() method in the ChartFactory class: 1 CategoryAxis categoryAxis = new CategoryAxis(categoryAxisLabel); 2 3 ValueAxis valueAxis = new NumberAxis(valueAxisLabel); BarRenderer renderer = new BarRenderer(); [snip...] 4 CategoryPlot plot = new CategoryPlot(dataset, categoryAxis, valueAxis, renderer); 5 plot.setOrientation(orientation); 6 JFreeChart chart = new JFreeChart(title, JFreeChart.DEFAULT TITLE FONT, plot, legend); Here’s what this code is doing: • Our bar chart has two axes, one that displays categories from the dataset (a CategoryAxis), and another that provides the numerical scale against which the data values are plotted (a NumberAxis). You can see these axes being constructed in lines 1 and 2 above, using the axis labels that we passed to the createBarChart() method. • At line 3, a BarRenderer is created—this is the class that is used to draw the bar for each data item. The renderer handles most of the drawing work, and you’ll see later that you can substitute another type of renderer to change the overall appearance of the chart. • The dataset, axes and renderer are all managed by a CategoryPlot, which coordinates most of the interaction between these components. When you customise charts, you’ll often need to get a reference to the chart’s plot, which in turn can give you access to the axes, renderer and dataset. At line 4, the plot is created, and the other components are assigned to it. • Finally, the plot is wrapped in a JFreeChart instance, with the specified title. The JFreeChart class provides the top-level access to a chart, but most of the “guts” of a chart is defined at the plot level (or in the objects managed by the plot, such as the axes, dataset(s) and renderer(s)). Armed with this knowledge of the internal structure of our chart, in the following sections, we’ll slowly customise our bar chart. 6.4 Simple Chart Customisation Some simple modifications to the appearance of a bar chart can be made by calling methods in the JFreeChart and CategoryPlot classes. For example, to change the background colours for the chart and plot: CHAPTER 6. BAR CHARTS 49 chart.setBackgroundPaint(Color.white); CategoryPlot plot = (CategoryPlot) chart.getPlot(); plot.setBackgroundPaint(Color.lightGray); plot.setRangeGridlinePaint(Color.white); This code fragment (from BarExample2.java) changes the background colour for the chart, then obtains a reference to the chart’s plot and modifies it as well—see figure 6.3. Figure 6.3: A bar chart (see BarExample2.java) A cast of the plot reference (to CategoryPlot) is required—it is safe to make this cast, because we know that a CategoryPlot is used for this chart type. JFreeChart uses other plot types (PiePlot, XYPlot, and so on) for different kinds of charts. You almost always need to cast the plot reference to one of these types, because the base class (Plot) only defines a few common attributes and methods. As you become more familiar with JFreeChart, you’ll learn which Plot subclass is used for each type of chart. In our example, we also use the plot reference to change the colour of the grid lines for the range axis. Take a look through the API documentation for the CategoryPlot class, to see what else you could modify here. 6.5 Customising the Renderer Recall from section 6.3 that the CategoryPlot manages a renderer which, in the case of a regular bar chart, is an instance of BarRenderer. If we obtain a reference to this renderer, a large number of customisation options become available. 6.5.1 Bar Colours To change the colours used for each series in the chart: BarRenderer renderer = (BarRenderer) plot.getRenderer(); renderer.setSeriesPaint(0, Color.gray); renderer.setSeriesPaint(1, Color.orange); renderer.setDrawBarOutline(false); This results in the chart shown in figure 6.4. Note that the setSeriesPaint() method is defined in the AbstractRenderer base class—you can use this for all types of renderer. CHAPTER 6. BAR CHARTS 50 Figure 6.4: A bar chart (see BarExample3.java) 6.5.2 Bar Spacing Within Categories Among other things, the renderer controls the spacing of bars within each category.1 So we could remove all the space between bars in the same category, as follows: renderer.setItemMargin(0.0); This results in the chart shown in figure 6.5. Notice how the bars have grown a little wider—this is because JFreeChart is now allocating less of the overall space to provide gaps between the bars, so the bars themselves resize a little bigger. Figure 6.5: A bar chart (see BarExample4.java) 1 The spacing between categories is controlled by the CategoryAxis. That will be covered later. Chapter 7 Line Charts 7.1 Introduction This section describes the line charts that can be created with JFreeChart. It is possible to create line charts using data from either the CategoryDataset interface or the XYDataset interface. 7.2 A Line Chart Based On A Category Dataset 7.2.1 Overview A line chart based on a CategoryDataset simply connects each (category, value) data item using straight lines. This section presents a sample application that generates the following chart shown in figure 7.1. Figure 7.1: A sample line chart The full source code for this demo (LineChartDemo1.java) is available for download with the JFreeChart Developer Guide. 7.2.2 The Dataset The first step in generating the chart is, as always, to create a dataset. In the example, the DefaultCategoryDataset class is used: DefaultCategoryDataset dataset = new DefaultCategoryDataset(); dataset.addValue(212, "Classes", "JDK 1.0"); dataset.addValue(504, "Classes", "JDK 1.1"); dataset.addValue(1520, "Classes", "SDK 1.2"); 51 CHAPTER 7. LINE CHARTS 52 dataset.addValue(1842, "Classes", "SDK 1.3"); dataset.addValue(2991, "Classes", "SDK 1.4"); Note that you can use any implementation of the CategoryDataset interface as your dataset. 7.2.3 Constructing the Chart The createLineChart() method in the ChartFactory class provides a convenient way to create the chart. Here is the code: // create the chart... JFreeChart chart = ChartFactory.createLineChart( "Java Standard Class Library", // chart title "Release", // domain axis label "Class Count", // range axis label dataset, // data PlotOrientation.VERTICAL, // orientation false, // include legend true, // tooltips false // urls ); This method constructs a JFreeChart object with a title, no legend, and plot with appropriate axes, renderer and tooltip generator. The dataset is the one created in the previous section. 7.2.4 Customising the Chart The chart will be initialised using default settings for most attributes. You are, of course, free to modify any of the settings to change the appearance of your chart. In this example, we customise the chart in the following ways: • two subtitles are added to the chart; • the chart background color is set to white; • the plot background color is set to light gray; • the gridline color is changed to white; • the range axis is modified to display integer values only; • the renderer is modified to fill shapes with white. The first subtitle is added at the default position (below the main title): chart.addSubtitle(new TextTitle("Number of Classes By Release")); The next subtitle takes a little extra code, to change the font, place it at the bottom of the chart, and align it to the right side: TextTitle source = new TextTitle( "Source: Java In A Nutshell (4th Edition) " + "by David Flanagan (O’Reilly)" ); source.setFont(new Font("SansSerif", Font.PLAIN, 10)); source.setPosition(RectangleEdge.BOTTOM); source.setHorizontalAlignment(HorizontalAlignment.RIGHT); chart.addSubtitle(source); Changing the chart’s background color is simple, because this is an attribute maintained by the JFreeChart class: chart.setBackgroundPaint(Color.white); To change other attributes, we first need to obtain a reference to the CategoryPlot object used by the chart: CHAPTER 7. LINE CHARTS 53 CategoryPlot plot = (CategoryPlot) chart.getPlot(); To set the background color for the plot, and change the gridline color: plot.setBackgroundPaint(Color.lightGray); plot.setRangeGridlinePaint(Color.white); The plot is responsible for drawing the data and axes on the chart. Some of this work is delegated to a renderer, which you can access via the getRenderer() method. The renderer maintains most of the attributes that relate to the appearance of the data items within the chart. LineAndShapeRenderer renderer = (LineAndShapeRenderer) plot.getRenderer(); renderer.setShapesVisible(true); renderer.setDrawOutlines(true); renderer.setUseFillPaint(true); The plot also manages the chart’s axes. In the example, the range axis is modified so that it only displays integer values for the tick labels: // change the auto tick unit selection to integer units only... NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis(); rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits()); There are many other ways to customise the chart. Please refer to the reference section of this document, the API documentation and the source code for details of the methods available. 7.2.5 The Complete Program The code for the demonstration application is presented in full, complete with the import statements. The source code is available for download from the same location as the JFreeChart Developer Guide. /* ------------------* LineChartDemo1.java * ------------------* (C) Copyright 2002-2005, by Object Refinery Limited. * */ package demo; import java.awt.Color; import java.awt.Dimension; import java.awt.Font; import javax.swing.JPanel; import import import import import import import import import import import import import import org.jfree.chart.ChartFactory; org.jfree.chart.ChartPanel; org.jfree.chart.JFreeChart; org.jfree.chart.axis.NumberAxis; org.jfree.chart.plot.CategoryPlot; org.jfree.chart.plot.PlotOrientation; org.jfree.chart.renderer.category.LineAndShapeRenderer; org.jfree.chart.title.TextTitle; org.jfree.data.category.CategoryDataset; org.jfree.data.category.DefaultCategoryDataset; org.jfree.ui.ApplicationFrame; org.jfree.ui.HorizontalAlignment; org.jfree.ui.RectangleEdge; org.jfree.ui.RefineryUtilities; /** * A simple demonstration application showing how to create a line chart using * data from a {@link CategoryDataset}. */ public class LineChartDemo1 extends ApplicationFrame { /** * Creates a new demo. * * @param title the frame title. */ public LineChartDemo1(String title) { super(title); CHAPTER 7. LINE CHARTS CategoryDataset dataset = createDataset(); JFreeChart chart = createChart(dataset); ChartPanel chartPanel = new ChartPanel(chart); chartPanel.setPreferredSize(new Dimension(500, 270)); setContentPane(chartPanel); } /** * Creates a sample dataset. * * @return The dataset. */ private static CategoryDataset createDataset() { DefaultCategoryDataset dataset = new DefaultCategoryDataset(); dataset.addValue(212, "Classes", "JDK 1.0"); dataset.addValue(504, "Classes", "JDK 1.1"); dataset.addValue(1520, "Classes", "SDK 1.2"); dataset.addValue(1842, "Classes", "SDK 1.3"); dataset.addValue(2991, "Classes", "SDK 1.4"); return dataset; } /** * Creates a sample chart. * * @param dataset a dataset. * * @return The chart. */ private static JFreeChart createChart(CategoryDataset dataset) { // create the chart... JFreeChart chart = ChartFactory.createLineChart( "Java Standard Class Library", // chart title "Release", // domain axis label "Class Count", // range axis label dataset, // data PlotOrientation.VERTICAL, // orientation false, // include legend true, // tooltips false // urls ); chart.addSubtitle(new TextTitle("Number of Classes By Release")); TextTitle source = new TextTitle( "Source: Java In A Nutshell (4th Edition) " + "by David Flanagan (O’Reilly)" ); source.setFont(new Font("SansSerif", Font.PLAIN, 10)); source.setPosition(RectangleEdge.BOTTOM); source.setHorizontalAlignment(HorizontalAlignment.RIGHT); chart.addSubtitle(source); chart.setBackgroundPaint(Color.white); CategoryPlot plot = (CategoryPlot) chart.getPlot(); plot.setBackgroundPaint(Color.lightGray); plot.setRangeGridlinePaint(Color.white); // customise the range axis... NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis(); rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits()); // customise the renderer... LineAndShapeRenderer renderer = (LineAndShapeRenderer) plot.getRenderer(); renderer.setShapesVisible(true); renderer.setDrawOutlines(true); renderer.setUseFillPaint(true); renderer.setFillPaint(Color.white); return chart; } /** * Creates a panel for the demo (used by SuperDemo.java). * * @return A panel. */ public static JPanel createDemoPanel() { JFreeChart chart = createChart(createDataset()); 54 CHAPTER 7. LINE CHARTS return new ChartPanel(chart); } /** * Starting point for the demonstration application. * * @param args ignored. */ public static void main(String[] args) { LineChartDemo1 demo = new LineChartDemo1("Line Chart Demo"); demo.pack(); RefineryUtilities.centerFrameOnScreen(demo); demo.setVisible(true); } } 55 CHAPTER 7. LINE CHARTS 7.3 56 A Line Chart Based On An XYDataset 7.3.1 Overview A line chart based on an XYDataset connects each (x, y) point with a straight line. This section presents a sample application that generates the chart shown in figure 7.2. Figure 7.2: A sample line chart using an XYPlot The complete source code (LineChartDemo2.java) is available to download with the JFreeChart Developer Guide. 7.3.2 The Dataset For this chart, an XYSeriesCollection is used as the dataset (you can use any implementation of the XYDataset interface). For the purposes of the self-contained demo, we create this dataset in code, as follows: XYSeries series1 series1.add(1.0, series1.add(2.0, series1.add(3.0, series1.add(4.0, series1.add(5.0, series1.add(6.0, series1.add(7.0, series1.add(8.0, = new XYSeries("First"); 1.0); 4.0); 3.0); 5.0); 5.0); 7.0); 7.0); 8.0); XYSeries series2 series2.add(1.0, series2.add(2.0, series2.add(3.0, series2.add(4.0, series2.add(5.0, series2.add(6.0, series2.add(7.0, series2.add(8.0, = new XYSeries("Second"); 5.0); 7.0); 6.0); 8.0); 4.0); 4.0); 2.0); 1.0); XYSeries series3 = new XYSeries("Third"); series3.add(3.0, 4.0); series3.add(4.0, 3.0); series3.add(5.0, 2.0); series3.add(6.0, 3.0); series3.add(7.0, 6.0); series3.add(8.0, 3.0); series3.add(9.0, 4.0); series3.add(10.0, 3.0); XYSeriesCollection dataset = new XYSeriesCollection(); dataset.addSeries(series1); dataset.addSeries(series2); dataset.addSeries(series3); return dataset; CHAPTER 7. LINE CHARTS 57 Notice how each series has x-values (not just y-values) that are independent from the other series. The dataset will also accept null in place of a y-value. When a null value is encountered, no connecting line is drawn, resulting in a discontinuous line for the series. 7.3.3 Constructing the Chart The createXYLineChart() method in the ChartFactory class provides a convenient way to create the chart: JFreeChart chart = ChartFactory.createXYLineChart( "Line Chart Demo 2", // chart title "X", // x axis label "Y", // y axis label dataset, // data PlotOrientation.VERTICAL, true, // include legend true, // tooltips false // urls ); This method constructs a JFreeChart object with a title, legend and plot with appropriate axes and renderer. The dataset is the one created in the previous section. The chart is created with a legend, and tooltips are enabled (URLs are disabled—these are only used in the creation of HTML image maps). 7.3.4 Customising the Chart The chart will be initialised using default settings for most attributes. You are, of course, free to modify any of the settings to change the appearance of your chart. In this example, several attributes are modified: • the chart background color; • the plot background color; • the axis offsets; • the color of the domain and range gridlines; • the renderer is modified to draw shapes as well as lines; • the tick unit collection for the range axis, so that the tick values always display integer values; Changing the chart’s background color is simple: // set the background color for the chart... chart.setBackgroundPaint(Color.white); Changing the plot background color, the axis offsets, and the color of the gridlines, requires a reference to the plot. The cast to XYPlot is required so that we can access methods specific to this type of plot: // get a reference to the plot for further customisation... XYPlot plot = (XYPlot) chart.getPlot(); plot.setBackgroundPaint(Color.lightGray); plot.setAxisOffset(new RectangleInsets(5.0, 5.0, 5.0, 5.0)); plot.setDomainGridlinePaint(Color.white); plot.setRangeGridlinePaint(Color.white); The renderer is modified to display filled shapes in addition to the default lines: XYLineAndShapeRenderer renderer = (XYLineAndShapeRenderer) plot.getRenderer(); renderer.setShapesVisible(true); renderer.setShapesFilled(true); CHAPTER 7. LINE CHARTS 58 The final modification is a change to the range axis. We change the default collection of tick units (which allow fractional values) to an integer-only collection: // change the auto tick unit selection to integer units only... NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis(); rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits()); Refer to the source code, Javadoc API documentation or elsewhere in this document for details of the other customisations that you can make to an XYPlot. 7.3.5 The Complete Program The code for the demonstration application is presented here in full, complete with the import statements: /* ------------------* LineChartDemo2.java * ------------------* (C) Copyright 2002-2005, by Object Refinery Limited. * */ package demo; import java.awt.Color; import javax.swing.JPanel; import import import import import import import import import import import import import org.jfree.chart.ChartFactory; org.jfree.chart.ChartPanel; org.jfree.chart.JFreeChart; org.jfree.chart.axis.NumberAxis; org.jfree.chart.plot.PlotOrientation; org.jfree.chart.plot.XYPlot; org.jfree.chart.renderer.xy.XYLineAndShapeRenderer; org.jfree.data.xy.XYDataset; org.jfree.data.xy.XYSeries; org.jfree.data.xy.XYSeriesCollection; org.jfree.ui.ApplicationFrame; org.jfree.ui.RectangleInsets; org.jfree.ui.RefineryUtilities; /** * A simple demonstration application showing how to create a line chart using * data from an {@link XYDataset}. *"); out.println("* IMPORTANT NOTE: THIS DEMO IS DOCUMENTED IN THE JFREECHART DEVELOPER GUIDE. * DO NOT MAKE CHANGES WITHOUT UPDATING THE GUIDE ALSO!! */ public class LineChartDemo2 extends ApplicationFrame { /** * Creates a new demo. * * @param title the frame title. */ public LineChartDemo2(String title) { super(title); XYDataset dataset = createDataset(); JFreeChart chart = createChart(dataset); ChartPanel chartPanel = new ChartPanel(chart); chartPanel.setPreferredSize(new java.awt.Dimension(500, 270)); setContentPane(chartPanel); } /** * Creates a sample dataset. * * @return a sample dataset. */ private static XYDataset createDataset() { XYSeries series1 = new XYSeries("First"); series1.add(1.0, 1.0); series1.add(2.0, 4.0); CHAPTER 7. LINE CHARTS series1.add(3.0, series1.add(4.0, series1.add(5.0, series1.add(6.0, series1.add(7.0, series1.add(8.0, 3.0); 5.0); 5.0); 7.0); 7.0); 8.0); XYSeries series2 series2.add(1.0, series2.add(2.0, series2.add(3.0, series2.add(4.0, series2.add(5.0, series2.add(6.0, series2.add(7.0, series2.add(8.0, = new XYSeries("Second"); 5.0); 7.0); 6.0); 8.0); 4.0); 4.0); 2.0); 1.0); XYSeries series3 = new XYSeries("Third"); series3.add(3.0, 4.0); series3.add(4.0, 3.0); series3.add(5.0, 2.0); series3.add(6.0, 3.0); series3.add(7.0, 6.0); series3.add(8.0, 3.0); series3.add(9.0, 4.0); series3.add(10.0, 3.0); XYSeriesCollection dataset = new XYSeriesCollection(); dataset.addSeries(series1); dataset.addSeries(series2); dataset.addSeries(series3); return dataset; } /** * Creates a chart. * * @param dataset the data for the chart. * * @return a chart. */ private static JFreeChart createChart(XYDataset dataset) { // create the chart... JFreeChart chart = ChartFactory.createXYLineChart( "Line Chart Demo 2", // chart title "X", // x axis label "Y", // y axis label dataset, // data PlotOrientation.VERTICAL, true, // include legend true, // tooltips false // urls ); // NOW DO SOME OPTIONAL CUSTOMISATION OF THE CHART... chart.setBackgroundPaint(Color.white); // get a reference to the plot for further customisation... XYPlot plot = (XYPlot) chart.getPlot(); plot.setBackgroundPaint(Color.lightGray); plot.setAxisOffset(new RectangleInsets(5.0, 5.0, 5.0, 5.0)); plot.setDomainGridlinePaint(Color.white); plot.setRangeGridlinePaint(Color.white); XYLineAndShapeRenderer renderer = (XYLineAndShapeRenderer) plot.getRenderer(); renderer.setShapesVisible(true); renderer.setShapesFilled(true); // change the auto tick unit selection to integer units only... NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis(); rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits()); // OPTIONAL CUSTOMISATION COMPLETED. return chart; } 59 CHAPTER 7. LINE CHARTS /** * Creates a panel for the demo (used by SuperDemo.java). * * @return A panel. */ public static JPanel createDemoPanel() { JFreeChart chart = createChart(createDataset()); return new ChartPanel(chart); } /** * Starting point for the demonstration application. * * @param args ignored. */ public static void main(String[] args) { LineChartDemo2 demo = new LineChartDemo2("Line Chart Demo 2"); demo.pack(); RefineryUtilities.centerFrameOnScreen(demo); demo.setVisible(true); } } 60 Chapter 8 Time Series Charts 8.1 Introduction Time series charts are very similar to line charts, except that the values on the domain axis are dates rather than numbers. This section describes how to create time series charts with JFreeChart. 8.2 8.2.1 Time Series Charts Overview A time series chart is really just a line chart using data obtained via the XYDataset interface (see the example in the previous section). The difference is that the x-values are displayed as dates on the domain axis. This section presents a sample application that generates the chart shown in figure 8.1. Figure 8.1: A time series chart The complete source code (TimeSeriesDemo1.java) for this example is available for download with the JFreeChart Developer Guide. 8.2.2 Dates or Numbers? Time series charts are created using data from an XYDataset. This interface doesn’t have any methods that return dates, so how does JFreeChart create time series charts? The x-values returned by the dataset are double primitives, but the values are interpreted in a special way—they are assumed to represent the number of milliseconds since midnight, 1 January 61 CHAPTER 8. TIME SERIES CHARTS 62 1970 (the encoding used by the java.util.Date class). A special axis class (DateAxis) converts from milliseconds to dates and back again as necessary, allowing the axis to display tick labels formatted as dates. 8.2.3 The Dataset For the demo chart, a TimeSeriesCollection is used as the dataset (you can use any implementation of the XYDataset interface): TimeSeries s1.add(new s1.add(new s1.add(new s1.add(new s1.add(new s1.add(new s1.add(new s1.add(new s1.add(new s1.add(new s1.add(new s1.add(new s1.add(new s1.add(new s1.add(new s1.add(new s1.add(new s1.add(new s1 = new TimeSeries("L&G European Index Trust", Month.class); Month(2, 2001), 181.8); Month(3, 2001), 167.3); Month(4, 2001), 153.8); Month(5, 2001), 167.6); Month(6, 2001), 158.8); Month(7, 2001), 148.3); Month(8, 2001), 153.9); Month(9, 2001), 142.7); Month(10, 2001), 123.2); Month(11, 2001), 131.8); Month(12, 2001), 139.6); Month(1, 2002), 142.9); Month(2, 2002), 138.7); Month(3, 2002), 137.3); Month(4, 2002), 143.9); Month(5, 2002), 139.8); Month(6, 2002), 137.0); Month(7, 2002), 132.8); TimeSeries s2.add(new s2.add(new s2.add(new s2.add(new s2.add(new s2.add(new s2.add(new s2.add(new s2.add(new s2.add(new s2.add(new s2.add(new s2.add(new s2.add(new s2.add(new s2.add(new s2.add(new s2.add(new s2 = new TimeSeries("L&G UK Index Trust", Month.class); Month(2, 2001), 129.6); Month(3, 2001), 123.2); Month(4, 2001), 117.2); Month(5, 2001), 124.1); Month(6, 2001), 122.6); Month(7, 2001), 119.2); Month(8, 2001), 116.5); Month(9, 2001), 112.7); Month(10, 2001), 101.5); Month(11, 2001), 106.1); Month(12, 2001), 110.3); Month(1, 2002), 111.7); Month(2, 2002), 111.0); Month(3, 2002), 109.6); Month(4, 2002), 113.2); Month(5, 2002), 111.6); Month(6, 2002), 108.8); Month(7, 2002), 101.6); TimeSeriesCollection dataset = new TimeSeriesCollection(); dataset.addSeries(s1); dataset.addSeries(s2); In the example, the series contain monthly data. However, the TimeSeries class can be used to represent values observed at other intervals (annual, daily, hourly etc). 8.2.4 Constructing the Chart The createTimeSeriesChart() method in the ChartFactory class provides a convenient way to create the chart: JFreeChart chart = ChartFactory.createTimeSeriesChart( "Legal & General Unit Trust Prices", // title "Date", // x-axis label "Price Per Unit", // y-axis label dataset, // data true, // create legend? true, // generate tooltips? false // generate URLs? ); This method constructs a JFreeChart object with a title, legend and plot with appropriate axes and renderer. The dataset is the one created in the previous section. CHAPTER 8. TIME SERIES CHARTS 8.2.5 63 Customising the Chart The chart will be initialised using default settings for most attributes. You are, of course, free to modify any of the settings to change the appearance of your chart. In this example, several attributes are modified: • the renderer is changed to display series shapes at each data point, in addition to the lines between data points; • a date format override is set for the domain axis; Modifying the renderer requires a couple of steps to obtain a reference to the renderer and then cast it to a XYLineAndShapeRenderer: XYItemRenderer r = plot.getRenderer(); if (r instanceof XYLineAndShapeRenderer) { XYLineAndShapeRenderer renderer = (XYLineAndShapeRenderer) r; renderer.setBaseShapesVisible(true); renderer.setBaseShapesFilled(true); } In the final customisation, a date format override is set for the domain axis. DateAxis axis = (DateAxis) plot.getDomainAxis(); axis.setDateFormatOverride(new SimpleDateFormat("MMM-yyyy")); When this is set, the axis will continue to “auto-select” a DateTickUnit from the collection of standard tick units, but it will ignore the formatting from the tick unit and use the override format instead. 8.2.6 The Complete Program The code for the demonstration application is presented in full, complete with the import statements: /* ------------------* TimeSeriesDemo.java * ------------------* (C) Copyright 2002-2005, by Object Refinery Limited. * */ package demo; import java.awt.Color; import java.text.SimpleDateFormat; import javax.swing.JPanel; import import import import import import import import import import import import import import org.jfree.chart.ChartFactory; org.jfree.chart.ChartPanel; org.jfree.chart.JFreeChart; org.jfree.chart.axis.DateAxis; org.jfree.chart.plot.XYPlot; org.jfree.chart.renderer.xy.XYItemRenderer; org.jfree.chart.renderer.xy.XYLineAndShapeRenderer; org.jfree.data.time.Month; org.jfree.data.time.TimeSeries; org.jfree.data.time.TimeSeriesCollection; org.jfree.data.xy.XYDataset; org.jfree.ui.ApplicationFrame; org.jfree.ui.RectangleInsets; org.jfree.ui.RefineryUtilities; /** * An example of a time series chart. For the most part, default settings are CHAPTER 8. TIME SERIES CHARTS * used, except that the renderer is modified to show filled shapes (as well as * lines) at each data point. *
* IMPORTANT NOTE: THIS DEMO IS DOCUMENTED IN THE JFREECHART DEVELOPER GUIDE. * DO NOT MAKE CHANGES WITHOUT UPDATING THE GUIDE ALSO!! */ public class TimeSeriesDemo1 extends ApplicationFrame { /** * A demonstration application showing how to create a simple time series * chart. This example uses monthly data. * * @param title the frame title. */ public TimeSeriesDemo1(String title) { super(title); XYDataset dataset = createDataset(); JFreeChart chart = createChart(dataset); ChartPanel chartPanel = new ChartPanel(chart); chartPanel.setPreferredSize(new java.awt.Dimension(500, 270)); chartPanel.setMouseZoomable(true, false); setContentPane(chartPanel); } /** * Creates a chart. * * @param dataset a dataset. * * @return A chart. */ private static JFreeChart createChart(XYDataset dataset) { JFreeChart chart = ChartFactory.createTimeSeriesChart( "Legal & General Unit Trust Prices", // title "Date", // x-axis label "Price Per Unit", // y-axis label dataset, // data true, // create legend? true, // generate tooltips? false // generate URLs? ); chart.setBackgroundPaint(Color.white); XYPlot plot = (XYPlot) chart.getPlot(); plot.setBackgroundPaint(Color.lightGray); plot.setDomainGridlinePaint(Color.white); plot.setRangeGridlinePaint(Color.white); plot.setAxisOffset(new RectangleInsets(5.0, 5.0, 5.0, 5.0)); plot.setDomainCrosshairVisible(true); plot.setRangeCrosshairVisible(true); XYItemRenderer r = plot.getRenderer(); if (r instanceof XYLineAndShapeRenderer) { XYLineAndShapeRenderer renderer = (XYLineAndShapeRenderer) r; renderer.setBaseShapesVisible(true); renderer.setBaseShapesFilled(true); } DateAxis axis = (DateAxis) plot.getDomainAxis(); axis.setDateFormatOverride(new SimpleDateFormat("MMM-yyyy")); return chart; } /** 64 CHAPTER 8. TIME SERIES CHARTS * Creates a dataset, consisting of two series of monthly data. * * @return the dataset. */ private static XYDataset createDataset() { TimeSeries s1.add(new s1.add(new s1.add(new s1.add(new s1.add(new s1.add(new s1.add(new s1.add(new s1.add(new s1.add(new s1.add(new s1.add(new s1.add(new s1.add(new s1.add(new s1.add(new s1.add(new s1.add(new s1 = new TimeSeries("L&G European Index Trust", Month.class); Month(2, 2001), 181.8); Month(3, 2001), 167.3); Month(4, 2001), 153.8); Month(5, 2001), 167.6); Month(6, 2001), 158.8); Month(7, 2001), 148.3); Month(8, 2001), 153.9); Month(9, 2001), 142.7); Month(10, 2001), 123.2); Month(11, 2001), 131.8); Month(12, 2001), 139.6); Month(1, 2002), 142.9); Month(2, 2002), 138.7); Month(3, 2002), 137.3); Month(4, 2002), 143.9); Month(5, 2002), 139.8); Month(6, 2002), 137.0); Month(7, 2002), 132.8); TimeSeries s2.add(new s2.add(new s2.add(new s2.add(new s2.add(new s2.add(new s2.add(new s2.add(new s2.add(new s2.add(new s2.add(new s2.add(new s2.add(new s2.add(new s2.add(new s2.add(new s2.add(new s2.add(new s2 = new TimeSeries("L&G UK Index Trust", Month.class); Month(2, 2001), 129.6); Month(3, 2001), 123.2); Month(4, 2001), 117.2); Month(5, 2001), 124.1); Month(6, 2001), 122.6); Month(7, 2001), 119.2); Month(8, 2001), 116.5); Month(9, 2001), 112.7); Month(10, 2001), 101.5); Month(11, 2001), 106.1); Month(12, 2001), 110.3); Month(1, 2002), 111.7); Month(2, 2002), 111.0); Month(3, 2002), 109.6); Month(4, 2002), 113.2); Month(5, 2002), 111.6); Month(6, 2002), 108.8); Month(7, 2002), 101.6); TimeSeriesCollection dataset = new TimeSeriesCollection(); dataset.addSeries(s1); dataset.addSeries(s2); dataset.setDomainIsPointsInTime(true); return dataset; } /** * Creates a panel for the demo (used by SuperDemo.java). * * @return A panel. */ public static JPanel createDemoPanel() { JFreeChart chart = createChart(createDataset()); return new ChartPanel(chart); } /** * Starting point for the demonstration application. 65 CHAPTER 8. TIME SERIES CHARTS * * @param args ignored. */ public static void main(String[] args) { TimeSeriesDemo1 demo = new TimeSeriesDemo1("Time Series Demo 1"); demo.pack(); RefineryUtilities.centerFrameOnScreen(demo); demo.setVisible(true); } } 66 Chapter 9 Customising Charts 9.1 Introduction JFreeChart has been designed to be highly customisable. There are many attributes that you can set to change the default appearance of your charts. In this section, some common techniques for customising charts are presented. 9.2 Chart Attributes 9.2.1 Overview At the highest level, you can customise the appearance of your charts using methods in the JFreeChart class. This allows you to control: • the chart border; • the chart title and sub-titles; • the background color and/or image; • the rendering hints that are used to draw the chart, including whether or not anti-aliasing is used; These items are described in the following sections. 9.2.2 The Chart Border JFreeChart can draw a border around the outside of a chart. By default, no border is drawn, but you can change this using the setBorderVisible() method. The color and line-style for the border are controlled by the setBorderPaint() and setBorderStroke() methods. Note: if you are displaying your chart inside a ChartPanel, then you might prefer to use the border facilities provided by Swing. 9.2.3 The Chart Title A chart has one title that can appear at the top, bottom, left or right of the chart (you can also add subtitles—see the next section). The title is an instance of TextTitle. You can obtain a reference to the title using the getTitle() method: TextTitle title = chart.getTitle(); To modify the title text (without changing the font or position): 67 CHAPTER 9. CUSTOMISING CHARTS 68 chart.setTitle("A Chart Title"); The placement of the title at the top, bottom, left or right of the chart is controlled by a property of the title itself. To move the title to the bottom of the chart: chart.getTitle().setPosition(RectangleEdge.BOTTOM); If you prefer to have no title on your chart, you can set the title to null. 9.2.4 Subtitles A chart can have any number of subtitles. To add a sub-title to a chart, create a subtitle (any subclass of Title) and add it to the chart. For example: TextTitle subtitle1 = new TextTitle("A Subtitle"); chart.addSubtitle(subtitle1); You can add as many sub-titles as you like to a chart, but keep in mind that as you add more sub-titles there will be less and less space available for drawing the chart. To modify an existing sub-title, you need to get a reference to the sub-title. For example: Title subtitle = chart.getSubtitle(0); You will need to cast the Title reference to an appropriate subclass before you can change its properties. You can check the number of sub-titles using the getSubtitleCount() method. 9.2.5 Setting the Background Color You can use the setBackgroundPaint() method to set the background color for a chart.1 For example: chart.setBackgroundPaint(Color.blue); You can use any implementation of the Paint interface, including the Java classes Color, GradientPaint and TexturePaint. For example: Paint p = new GradientPaint(0, 0, Color.white, 1000, 0, Color.green)); chart.setBackgroundPaint(p); You can also set the background paint to null, which is recommended if you have specified a background image for your chart. 9.2.6 Using a Background Image You can use the setBackgroundImage() method to set a background image for a chart. chart.setBackgroundImage(JFreeChart.INFO.getLogo()); By default, the image will be scaled to fit the area that the chart is being drawn into, but you can change this using the setBackgroundImageAlignment() method. chart.setBackgroundImageAlignment(Align.TOP LEFT); Using the setBackgroundImageAlpha() method, you can control the alpha-transparency for the image. If you want an image to fill only the data area of your chart (that is, the area inside the axes), then you need to add a background image to the chart’s Plot (described later). 1 You can also set the background color for the chart’s plot area, which has a slightly different effect—refer to the Plot class for details. CHAPTER 9. CUSTOMISING CHARTS 9.2.7 69 Rendering Hints JFreeChart uses the Java2D API to draw charts. Within this API, you can specify rendering hints to fine tune aspects of the way that the rendering engine works. JFreeChart allows you to specify the rendering hints to be passed to the Java2D API when charts are drawn—use the setRenderingHints() method. As a convenience, a method is provided to turn anti-aliasing on or off. With anti-aliasing on, charts appear to be smoother but they take longer to draw: // turn on antialiasing... chart.setAntiAlias(true); By default, charts are drawn with anti-aliasing turned on. 9.3 Plot Attributes 9.3.1 Overview The JFreeChart class delegates a lot of the work in drawing a chart to the Plot class (or, rather, to a specific subclass of Plot). The getPlot() method in the JFreeChart class returns a reference to the plot being used by the chart. Plot plot = chart.getPlot(); You may need to cast this reference to a specific subclass of Plot, for example: CategoryPlot plot = chart.getCategoryPlot(); ...or: XYPlot plot = chart.getXYPlot(); Note that these methods will throw a ClassCastException if the plot is not an appropriate class. 9.3.2 Which Plot Subclass? How do you know which subclass of Plot is being used by a chart? As you gain experience with JFreeChart, it will become clear which charts use CategoryPlot and which charts use XYPlot. If in doubt, take a look in the ChartFactory class source code to see how each chart type is put together. 9.3.3 Setting the Background Paint You can use the setBackgroundPaint() method to set the background color for a plot. For example: Plot plot = chart.getPlot(); plot.setBackgroundPaint(Color.white); You can use any implementation of the Paint interface, including the Java classes Color, GradientPaint and TexturePaint. You can also set the background paint to null. 9.3.4 Using a Background Image You can use the setBackgroundImage() method to set a background image for a plot: Plot plot = chart.getPlot(); plot.setBackgroundImage(JFreeChart.INFO.getLogo()); By default, the image will be scaled to fit the area that the plot is being drawn into. You can change this using the setBackgroundImageAlignment() method: plot.setBackgroundImageAlignment(Align.BOTTOM RIGHT); Use the setBackgroundAlpha() method to control the alpha-transparency used for the image. If you prefer your image to fill the entire chart area, then you need to add a background image to the JFreeChart object (described previously). CHAPTER 9. CUSTOMISING CHARTS 9.4 70 Axis Attributes 9.4.1 Overview The majority of charts created with JFreeChart have two axes, a domain axis and a range axis. Of course, there are some charts (for example, pie charts) that don’t have axes at all. For charts where axes are used, the Axis objects are managed by the plot. 9.4.2 Obtaining an Axis Reference Before you can change the properties of an axis, you need to obtain a reference to the axis. The plot classes CategoryPlot and XYPlot both have methods getDomainAxis() and getRangeAxis(). These methods return a reference to a ValueAxis, except in the case of the CategoryPlot, where the domain axis is an instance of CategoryAxis. // get an axis reference... CategoryPlot plot = chart.getCategoryPlot(); CategoryAxis domainAxis = plot.getDomainAxis(); // change axis properties... domainAxis.setLabel("Categories"); domainAxis.setLabelFont(someFont); There are many different subclasses of the CategoryAxis and ValueAxis classes. Sometimes you will need to cast your axis reference to a more specific subclass, in order to access some of its attributes. For example, if you know that your range axis is a NumberAxis (and the range axis almost always is), then you can do the following: XYPlot plot = chart.getXYPlot(); NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis(); rangeAxis.setAutoRange(false); 9.4.3 Setting the Axis Label You can use the setLabel() method to change the axis label. If you would prefer not to have a label for your axis, just set it to null. You can change the font, color and insets (the space around the outside of the label) with the methods setLabelFont(), setLabelPaint(), and setLabelInsets(), defined in the Axis class. 9.4.4 Rotating Axis Labels When an axis is drawn at the left or right of a plot (a “vertical” axis), the label is automatically rotated by 90 degrees to minimise the space required. If you prefer to have the label drawn horizontally, you can change the label angle: XYPlot plot = chart.getXYPlot(); ValueAxis axis = plot.getRangeAxis(); axis.setLabelAngle(Math.PI / 2.0); Note that the angle is specified in radians (Math.PI = 180 degrees). 9.4.5 Hiding Tick Labels To hide the tick labels for an axis: CategoryPlot plot = chart.getCategoryPlot(); ValueAxis axis = plot.getRangeAxis(); axis.setTickLabelsVisible(false); For a CategoryAxis, setTickLabelsVisible(false) will hide the category labels. CHAPTER 9. CUSTOMISING CHARTS 9.4.6 71 Hiding Tick Marks To hide the tick marks for an axis: XYPlot plot = chart.getXYPlot(); Axis axis = plot.getDomainAxis(); axis.setTickMarksVisible(false); Category axes do not have tick marks. 9.4.7 Setting the Tick Size By default, numerical and date axes automatically select a tick size so that the tick labels will not overlap. You can override this by setting your own tick unit using the setTickUnit() method. Alternatively, for a NumberAxis or a DateAxis you can specify your own set of tick units from which the axis will automatically select an appropriate tick size. This is described in the following sections. 9.4.8 Specifying “Standard” Number Tick Units In the NumberAxis class, there is a method setStandardTickUnits() that allows you to supply your own set of tick units for the “auto tick unit selection” mechanism. One common application is where you have a number axis that should only display integers. In this case, you don’t want tick units of (say) 0.5 or 0.25. There is a (static) method in the NumberAxis class that returns a set of standard integer tick units: XYPlot plot = chart.getXYPlot(); NumberAxis axis = (NumberAxis) plot.getRangeAxis(); TickUnitSource units = NumberAxis.createIntegerTickUnits(); axis.setStandardTickUnits(units); You are free to create your own TickUnits collection, if you want greater control over the standard tick units. 9.4.9 Specifying “Standard” Date Tick Units Similar to the case in the previous section, the DateAxis class has a method setStandardTickUnits() that allows you to supply your own set of tick units for the “auto tick unit selection” mechanism. The createStandardDateTickUnits() method returns the default collection for a DateAxis, but you are free to create your own TickUnits collection if you want greater control over the standard tick units. Chapter 10 Dynamic Charts 10.1 Overview To illustrate the use of JFreeChart for creating “dynamic” charts, this section presents a sample application that displays a frequently updating chart of JVM memory usage and availability. Figure 10.1: A dynamic chart demo 10.2 Background 10.2.1 Event notification JFreeChart uses an event notification mechanism that allows it to respond to changes to any component of the chart. For example, whenever a dataset is updated, a DatasetChangeEvent is sent to all listeners that are registered with the dataset. This triggers the following sequence of events: • the plot (which registers itself with the dataset as a DatasetChangeListener) receives notification of the dataset change. It updates the axis ranges (if necessary) then passes on a PlotChangeEvent to all its registered listeners; • the chart receives notification of the plot change event, and passes on a ChartChangeEvent to all its registered listeners; • finally, for charts that are displayed in a ChartPanel, the panel will receive the chart change event. It responds by redrawing the chart—a complete redraw, not just the updated data. A similar sequence of events happens for all changes to a chart or its subcomponents. 72 CHAPTER 10. DYNAMIC CHARTS 10.2.2 73 Performance Regarding performance, you need to be aware that JFreeChart wasn’t designed specifically for generating real-time charts. Each time a dataset is updated, the ChartPanel reacts by redrawing the entire chart. Optimisations, such as only drawing the most recently added data point, are difficult to implement in the general case, even more so given the Graphics2D abstraction (in the Java2D API) employed by JFreeChart. This limits the number of “frames per second” you will be able to achieve with JFreeChart. Whether this will be an issue for you depends on your data, the requirements of your application, and your operating environment. 10.3 The Demo Application 10.3.1 Overview The MemoryUsageDemo.java demonstration is included in the JFreeChart demo collection (source code available to purchasers of this guide). You can obtain this from: http://www.object-refinery.com/jfreechart/premium/index.html You will need to enter the username and password supplied with your original purchase of the JFreeChart Developer Guide. 10.3.2 Creating the Dataset The dataset is created using two TimeSeries objects (one for the total memory and the other for the free memory) that are added to a single time series collection: // create two series that automatically discard data > 30 seconds old... this.total = new TimeSeries("Total", Millisecond.class); this.total.setMaximumItemAge(30000); this.free = new TimeSeries("Free", Millisecond.class); this.free.setMaximumItemAge(30000); TimeSeriesCollection dataset = new TimeSeriesCollection(); dataset.addSeries(this.total); dataset.addSeries(this.free); The maximumItemAge attribute for each time series is set to 30,000 milliseconds (or 30 seconds) so that whenever new data is added to the series, any observations that are older that 30 seconds are automatically discarded. 10.3.3 Creating the Chart The chart creation (and customisation) follows the standard pattern for all charts. No special steps are required to create a dynamic chart, except that you should ensure that the axes have their autoRange attribute set to true. It also helps to retain a reference to the dataset used in the chart. 10.3.4 Updating the Dataset In the demo, the dataset is updated by adding data to the two time series from a separate thread, managed by the following timer: class DataGenerator extends Timer implements ActionListener { DataGenerator(int interval) { super(interval, null); addActionListener(this); } public void actionPerformed(ActionEvent event) { long f = Runtime.getRuntime().freeMemory(); long t = Runtime.getRuntime().totalMemory(); addTotalObservation(t); addFreeObservation(f); CHAPTER 10. DYNAMIC CHARTS 74 } } Note that JFreeChart does not yet use thread synchronisation between the chart drawing code and the dataset update code, so this approach is a little unsafe. One other point to note, at one point while investigating reports of a memory leak in JFreeChart, I left this demo running on a test machine for about six days. As the chart updates, you can see the effect of the garbage collector. Over the six day period, the total memory used remained constant while the free memory decreased as JFreeChart discarded temporary objects (garbage), and increased at the points where the garbage collector did its work. 10.3.5 Source Code For reference, here is the complete source code for the example: /* -------------------* MemoryUsageDemo.java * -------------------* (C) Copyright 2002-2006, by Object Refinery Limited. */ package demo; import import import import import import import import java.awt.BasicStroke; java.awt.BorderLayout; java.awt.Color; java.awt.Font; java.awt.event.ActionEvent; java.awt.event.ActionListener; java.awt.event.WindowAdapter; java.awt.event.WindowEvent; import import import import javax.swing.BorderFactory; javax.swing.JFrame; javax.swing.JPanel; javax.swing.Timer; import import import import import import import import import import import org.jfree.chart.ChartPanel; org.jfree.chart.JFreeChart; org.jfree.chart.axis.DateAxis; org.jfree.chart.axis.NumberAxis; org.jfree.chart.plot.XYPlot; org.jfree.chart.renderer.xy.XYItemRenderer; org.jfree.chart.renderer.xy.XYLineAndShapeRenderer; org.jfree.data.time.Millisecond; org.jfree.data.time.TimeSeries; org.jfree.data.time.TimeSeriesCollection; org.jfree.ui.RectangleInsets; /** * A demo application showing a dynamically * current JVM memory usage. *
* IMPORTANT NOTE: THIS DEMO IS DOCUMENTED * DO NOT MAKE CHANGES WITHOUT UPDATING THE */ public class MemoryUsageDemo extends JPanel updated chart that displays the IN THE JFREECHART DEVELOPER GUIDE. GUIDE ALSO!! { /** Time series for total memory used. */ private TimeSeries total; /** Time series for free memory. */ private TimeSeries free; /** * Creates a new application. * * @param maxAge the maximum age (in milliseconds). */ public MemoryUsageDemo(int maxAge) { super(new BorderLayout()); // create two series that automatically discard data more than 30 CHAPTER 10. DYNAMIC CHARTS // seconds old... this.total = new TimeSeries("Total Memory", Millisecond.class); this.total.setMaximumItemAge(maxAge); this.free = new TimeSeries("Free Memory", Millisecond.class); this.free.setMaximumItemAge(maxAge); TimeSeriesCollection dataset = new TimeSeriesCollection(); dataset.addSeries(this.total); dataset.addSeries(this.free); DateAxis domain = new DateAxis("Time"); NumberAxis range = new NumberAxis("Memory"); domain.setTickLabelFont(new Font("SansSerif", Font.PLAIN, 12)); range.setTickLabelFont(new Font("SansSerif", Font.PLAIN, 12)); domain.setLabelFont(new Font("SansSerif", Font.PLAIN, 14)); range.setLabelFont(new Font("SansSerif", Font.PLAIN, 14)); XYItemRenderer renderer = new XYLineAndShapeRenderer(true, false); renderer.setSeriesPaint(0, Color.red); renderer.setSeriesPaint(1, Color.green); renderer.setStroke(new BasicStroke(3f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL)); XYPlot plot = new XYPlot(dataset, domain, range, renderer); plot.setBackgroundPaint(Color.lightGray); plot.setDomainGridlinePaint(Color.white); plot.setRangeGridlinePaint(Color.white); plot.setAxisOffset(new RectangleInsets(5.0, 5.0, 5.0, 5.0)); domain.setAutoRange(true); domain.setLowerMargin(0.0); domain.setUpperMargin(0.0); domain.setTickLabelsVisible(true); range.setStandardTickUnits(NumberAxis.createIntegerTickUnits()); JFreeChart chart = new JFreeChart("JVM Memory Usage", new Font("SansSerif", Font.BOLD, 24), plot, true); chart.setBackgroundPaint(Color.white); ChartPanel chartPanel = new ChartPanel(chart); chartPanel.setBorder(BorderFactory.createCompoundBorder( BorderFactory.createEmptyBorder(4, 4, 4, 4), BorderFactory.createLineBorder(Color.black))); add(chartPanel); } /** * Adds an observation to the ’total memory’ time series. * * @param y the total memory used. */ private void addTotalObservation(double y) { this.total.add(new Millisecond(), y); } /** * Adds an observation to the ’free memory’ time series. * * @param y the free memory. */ private void addFreeObservation(double y) { this.free.add(new Millisecond(), y); } /** * The data generator. */ class DataGenerator extends Timer implements ActionListener { /** * Constructor. * * @param interval the interval (in milliseconds) */ DataGenerator(int interval) { super(interval, null); addActionListener(this); } /** * Adds a new free/total memory reading to the dataset. * * @param event the action event. 75 CHAPTER 10. DYNAMIC CHARTS */ public void actionPerformed(ActionEvent event) { long f = Runtime.getRuntime().freeMemory(); long t = Runtime.getRuntime().totalMemory(); addTotalObservation(t); addFreeObservation(f); } } /** * Entry point for the sample application. * * @param args ignored. */ public static void main(String[] args) { JFrame frame = new JFrame("Memory Usage Demo"); MemoryUsageDemo panel = new MemoryUsageDemo(30000); frame.getContentPane().add(panel, BorderLayout.CENTER); frame.setBounds(200, 120, 600, 280); frame.setVisible(true); panel.new DataGenerator(100).start(); frame.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); } } 76 Chapter 11 Tooltips 11.1 Overview JFreeChart includes mechanisms for generating, collecting and displaying tool tips for individual components of a chart. In this section, I describe: • how to generate tool tips (including customisation of tool tips); • how tool tips are collected; • how to display tool tips; • how to disable tool tips if you don’t need them; 11.2 Generating Tool Tips If you want to use tool tips, you need to make sure they are generated as your chart is being drawn. You do this by setting a tool tip generator for your plot or, in many cases, the plot’s item renderer. In the sub-sections that follow, I describe how to set a tool tip generator for the common chart types. 11.2.1 Pie Charts The PiePlot class generates tool tips using the PieToolTipGenerator interface. A standard implementation (StandardPieToolTipGenerator) is provided, and you are free to create your own implementations. To set the tool tip generator, use the following method in the PiePlot class: å public void setToolTipGenerator(PieToolTipGenerator generator); Sets the tool tip generator for the pie chart. If you set this to null, no tool tips will be generated. 11.2.2 Category Charts Category charts—including most of the bar charts generated by JFreeChart—are based on the CategoryPlot class and use a CategoryItemRenderer to draw each data item. The CategoryToolTipGenerator interface specifies the method via which the renderer will obtain tool tips (if required). To set the tool tip generator for a category plot’s item renderer, use the following method (defined in the AbstractCategoryItemRenderer class): 77 CHAPTER 11. TOOLTIPS 78 å public void setToolTipGenerator(CategoryToolTipGenerator generator); Sets the tool tip generator for the renderer. If you set this to null, no tool tips will be generated. 11.2.3 XY Charts XY charts—including scatter plots and all the time series charts generated by JFreeChart—are based on the XYPlot class and use an XYItemRenderer to draw each data item. The renderer generates tool tips (if required) using an XYToolTipGenerator. To set the tool tip generator for an XY plot’s item renderer, use the following method (defined in the AbstractXYItemRenderer class): å public void setToolTipGenerator(XYToolTipGenerator generator); Sets the tool tip generator for the renderer. If you set this to null, no tool tips will be generated. 11.3 Collecting Tool Tips Tool tips are collected, along with other chart entity information, using the ChartRenderingInfo class. You need to supply an instance of this class to JFreeChart’s draw() method, otherwise no tool tip information will be recorded (even if a generator has been registered with the plot or the plot’s item renderer, as described in the previous sections). Fortunately, the ChartPanel class takes care of this automatically, so if you are displaying your charts using the ChartPanel class you do not need to worry about how tool tips are collected—it is done for you. 11.4 Displaying Tool Tips Tool tips are automatically displayed by the ChartPanel class, provided that you have set up a tool tip generator for the plot (or the plot’s renderer). You can also enable or disable the display of tool tips in the ChartPanel class, using this method: å public void setDisplayToolTips(boolean flag); Switches the display of tool tips on or off. 11.5 Disabling Tool Tips The most effective way to disable tool tips is to set the tool tip generator to null. This ensures that no tool tip information is even generated, which can save memory and processing time (particularly for charts with large datasets). You can also disable the display of tool tips in the ChartPanel class, using the method given in the previous section. 11.6 Customising Tool Tips You can take full control of the text generated for each tool tip by providing your own implementation of the appropriate tool tip generator interface. Chapter 12 Item Labels 12.1 Introduction 12.1.1 Overview For many chart types, JFreeChart will allow you to display item labels in, on or near to each data item in a chart. For example, you can display the actual value represented by the bars in a bar chart—see figure 12.1. Figure 12.1: A bar chart with item labels This chapter covers how to: • make item labels visible (for the chart types that support item labels); • change the appearance (font and color) of item labels; • specify the location of item labels; • customise the item label text. A word of advice: use this feature sparingly. Charts are supposed to summarise your data—if you feel it is necessary to display the actual data values all over your chart, then perhaps your data is better presented in a table format. 79 CHAPTER 12. ITEM LABELS 12.1.2 80 Limitations There are some limitations with respect to the item labels in the current release of JFreeChart: • some renderers do not support item labels; • axis ranges are not automatically adjusted to take into account the item labels—some labels may disappear off the chart if sufficient margins are not set (use the setUpperMargin() and/or setLowerMargin() methods in the relevant axis to adjust this). In future releases of JFreeChart, some or all of these limitations will be addressed. 12.2 Displaying Item Labels 12.2.1 Overview Item labels are not visible by default, so you need to configure the renderer to create and display them. This involves two steps: • assign a CategoryItemLabelGenerator or XYItemLabelGenerator to the renderer—this is an object that assumes responsibility for creating the labels; • set a flag in the renderer to make the labels visible, either for all series or, if you prefer, on a per series basis. In addition, you have the option to customise the position, font and color of the item labels. These steps are detailed in the following sections. 12.2.2 Assigning a Label Generator Item labels are created by a label generator that is assigned to a renderer (the same mechanism is also used for tooltips). To assign a generator to a CategoryItemRenderer, use the following code: CategoryItemRenderer renderer = plot.getRenderer(); CategoryItemLabelGenerator generator = new StandardCategoryItemLabelGenerator( "{2}", new DecimalFormat("0.00")); renderer.setLabelGenerator(generator); Similarly, to assign a generator to an XYItemRenderer, use the following code: XYItemRenderer renderer = plot.getRenderer(); XYItemLabelGenerator generator = new StandardXYItemLabelGenerator( "{2}", new DecimalFormat("0.00")); renderer.setLabelGenerator(generator); You can customise the behaviour of the standard generator via settings that you can apply in the constructor, or you can create your own generator as described in section 12.5.2. 12.2.3 Making Labels Visible For All Series The setItemLabelsVisible() method sets a flag that controls whether or not the item labels are displayed (note that a label generator must be assigned to the renderer, or there will be no labels to display). For a CategoryItemRenderer: CategoryItemRenderer renderer = plot.getRenderer(); renderer.setItemLabelsVisible(true); Similarly, for a XYItemRenderer: XYItemRenderer renderer = plot.getRenderer(); renderer.setItemLabelsVisible(true); Once set, this flag takes precedence over any per series settings you may have made elsewhere. In order for the per series settings to apply, you need to set this flag to null (see section 12.2.4). CHAPTER 12. ITEM LABELS 12.2.4 81 Making Labels Visible For Selected Series If you prefer, you can set flags that control the visibility of the item labels on a per series basis. For example, item labels are displayed only for the first series in figure 12.2. Figure 12.2: Item labels for selected series only You can use code similar to the following: CategoryItemRenderer renderer = plot.getRenderer(); renderer.setItemLabelsVisible(null); // clears the ALL series flag renderer.setSeriesItemLabelsVisible(0, true); renderer.setSeriesItemLabelsVisible(1, false); Notice that the flag for “all series” has been set to null—this is important, because the “all series” flag takes precedence over the “per series” flags. 12.2.5 Troubleshooting If, after following the steps outlined in the previous sections, you still can’t see any labels on your chart, there are a couple of things to consider: • the renderer must have a label generator assigned to it—this is an object that creates the text items that are used for each label. • some renderers don’t yet support the display of item labels (refer to the documentation for the renderer you are using). 12.3 Item Label Appearance 12.3.1 Overview You can change the appearance of the item labels by changing the font and/or the color used to display the labels. As for most other renderer attributes, the settings can be made once for all series, or on a per series basis. In the current release of JFreeChart, labels are drawn with a transparent background. You cannot set a background color for the labels, nor can you specify that a border be drawn around the labels. This may change in the future. CHAPTER 12. ITEM LABELS 12.3.2 82 Changing the Label Font To change the font for the item labels in all series, you can use code similar to the following: CategoryItemRenderer renderer = plot.getRenderer(); renderer.setItemLabelFont(new Font("SansSerif", Font.PLAIN, 10)); Similarly, to set the font for individual series: CategoryItemRenderer renderer = plot.getRenderer(); // clear the settings for ALL series... renderer.setItemLabelFont(null); // add settings for individual series... renderer.setSeriesItemLabelFont(0, new Font("SansSerif", Font.PLAIN, 10)); renderer.setSeruesItemLabelFont(1, new Font("SansSerif", Font.BOLD, 10)); Notice how the font for all series has be set to null to prevent it from overriding the per series settings. 12.3.3 Changing the Label Color To change the color for the item labels in all series, you can use code similar to the following: CategoryItemRenderer renderer = plot.getRenderer(); renderer.setItemLabelPaint(Color.red); Similarly, to set the color for individual series: CategoryItemRenderer renderer = plot.getRenderer(); // clear the settings for ALL series... renderer.setItemLabelPaint(null); // add settings for individual series... renderer.setSeriesItemLabelPaint(0, Color.red); renderer.setSeriesItemLabelPaint(1, Color.blue); Once again, notice how the paint for all series has been set to null to prevent it from overriding the per series settings. 12.4 Item Label Positioning 12.4.1 Overview The positioning of item labels is controlled by four attributes that are combined into an ItemLabelPosition object. You can define label positions for items with positive and negative values independently, via the following methods in the CategoryItemRenderer interface: public void setPositiveItemLabelPosition(ItemLabelPosition position); public void setNegativeItemLabelPosition(ItemLabelPosition position); Understanding how these attributes impact the final position of individual labels is key to getting good results from the item label features in JFreeChart. There are four attributes: • the item label anchor - determines the base location for the item label; • the text anchor - determines the point on the label that is aligned to the base location; • the rotation anchor - this is the point on the label text about which the rotation (if any) is applied; • the rotation angle - the angle through which the label is rotated. These are described in the following sections. CHAPTER 12. ITEM LABELS 12.4.2 83 The Item Label Anchor The purpose of the item label anchor setting is to determine an (x, y) location on the chart that is near to the data item that is being labelled. The label is then aligned to this anchor point when it is being drawn. Refer to the ItemLabelAnchor documentation for more information. 12.4.3 The Text Anchor The text anchor determines which point on the label should be aligned with the anchor point described in the previous section. It is possible to align the center of the label with the anchor point, or the top-right of the label, or the bottom-left, and so on...refer to the TextAnchor documentation for all the options. Running the DrawStringDemo application in the org.jfree.demo package (included in the JCommon distribution) is a good way to gain an understanding of how the text anchor is used to align labels to a point on the screen. 12.4.4 The Rotation Anchor The rotation anchor defines a point on the label about which the rotation (if any) will be applied to the label. The DrawStringDemo class also demonstrates this feature. 12.4.5 The Rotation Angle The rotation angle defines the angle through which the label is rotated. The angle is specified in radians, and the rotation point is defined by the rotation anchor described in the previous section. 12.5 Customising the Item Label Text 12.5.1 Overview Up to this point, we’ve relied on the label generator built in to JFreeChart to create the text for the item labels. If you want to have complete control over the label text, you can write your own class that implements the CategoryItemLabelGenerator interface. In this section I provide a brief overview of the technique for implementing a custom label generator, then present two examples to illustrate the type of results you can achieve with this technique. 12.5.2 Implementing a Custom Item Label Generator To develop a custom label generator, you simply need to write a class that implements the method defined in the CategoryItemLabelGenerator interface: public String generateLabel(CategoryDataset dataset, int series, int category); The renderer will call this method at the point that it requires a String use for a label, and will pass in the CategoryDataset and the series and category indices for the current item. This means that you have full access to the entire dataset (not just the current item) for the creation of the label. The method can return an arbitrary String value, so you can apply any formatting you want to the result. It is also valid to return null if you prefer no label to be displayed. All this is best illustrated by way of examples, which are provided in the following sections. CHAPTER 12. ITEM LABELS 12.6 Example 1 - Values Above a Threshold 12.6.1 Overview 84 In this first example, the goal is to display labels for the items that have a value greater than some predefined threshold value (see figure 12.3). Figure 12.3: Item labels above a threshold It isn’t all that difficult to achieve, we simply need to: • write a class that implements the CategoryItemLabelGenerator interface, and implement the generateItemLabel() method in such a way that it returns null for any item where the value is less than the threshold; • create an instance of this new class, and assign it to the renderer using the setLabelGenerator() method. 12.6.2 Source Code The complete source code is presented below. /* ------------------* ItemLabelDemo1.java * ------------------* (C) Copyright 2004, 2005, by Object Refinery Limited. * */ package demo; import import import import java.awt.Color; java.awt.Dimension; java.awt.Font; java.text.NumberFormat; import javax.swing.JPanel; import import import import import import import import import import import org.jfree.chart.ChartFactory; org.jfree.chart.ChartPanel; org.jfree.chart.JFreeChart; org.jfree.chart.axis.NumberAxis; org.jfree.chart.labels.AbstractCategoryItemLabelGenerator; org.jfree.chart.labels.CategoryItemLabelGenerator; org.jfree.chart.plot.CategoryPlot; org.jfree.chart.plot.PlotOrientation; org.jfree.chart.renderer.category.CategoryItemRenderer; org.jfree.data.category.CategoryDataset; org.jfree.data.category.DefaultCategoryDataset; CHAPTER 12. ITEM LABELS import org.jfree.ui.ApplicationFrame; import org.jfree.ui.RefineryUtilities; /** * A simple demo showing a label generator that only displays labels for items * with a value that is greater than some threshold. */ public class ItemLabelDemo1 extends ApplicationFrame { /** * A custom label generator. */ static class LabelGenerator extends AbstractCategoryItemLabelGenerator implements CategoryItemLabelGenerator { /** The threshold. */ private double threshold; /** * Creates a new generator that only displays labels that are greater * than or equal to the threshold value. * * @param threshold the threshold value. */ public LabelGenerator(double threshold) { super("", NumberFormat.getInstance()); this.threshold = threshold; } /** * Generates a label for the specified item. The label is typically a * formatted version of the data value, but any text can be used. * * @param dataset the dataset (
null
not permitted). * @param series the series index (zero-based). * @param category the category index (zero-based). * * @return the label (possiblynull
). */ public String generateLabel(CategoryDataset dataset, int series, int category) { String result = null; Number value = dataset.getValue(series, category); if (value != null) { double v = value.doubleValue(); if (v > this.threshold) { result = value.toString(); // could apply formatting here } } return result; } } /** * Creates a new demo instance. * * @param title the frame title. */ public ItemLabelDemo1(String title) { super(title); CategoryDataset dataset = createDataset(); JFreeChart chart = createChart(dataset); ChartPanel chartPanel = new ChartPanel(chart); chartPanel.setPreferredSize(new Dimension(500, 270)); setContentPane(chartPanel); } /** * Returns a sample dataset. * * @return The dataset. */ private static CategoryDataset createDataset() { DefaultCategoryDataset dataset = new DefaultCategoryDataset(); 85 CHAPTER 12. ITEM LABELS dataset.addValue(11.0, dataset.addValue(44.3, dataset.addValue(93.0, dataset.addValue(35.6, dataset.addValue(75.1, return dataset; "S1", "S1", "S1", "S1", "S1", "C1"); "C2"); "C3"); "C4"); "C5"); } /** * Creates a sample chart. * * @param dataset the dataset. * * @return the chart. */ private static JFreeChart createChart(CategoryDataset dataset) { // create the chart... JFreeChart chart = ChartFactory.createBarChart( "Item Label Demo 1", // chart title "Category", // domain axis label "Value", // range axis label dataset, // data PlotOrientation.VERTICAL, // orientation false, // include legend true, // tooltips? false // URLs? ); chart.setBackgroundPaint(Color.white); CategoryPlot plot = chart.getCategoryPlot(); plot.setBackgroundPaint(Color.lightGray); plot.setDomainGridlinePaint(Color.white); plot.setRangeGridlinePaint(Color.white); NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis(); rangeAxis.setUpperMargin(0.15); CategoryItemRenderer renderer = plot.getRenderer(); renderer.setItemLabelGenerator(new LabelGenerator(50.0)); renderer.setItemLabelFont(new Font("Serif", Font.PLAIN, 20)); renderer.setItemLabelsVisible(true); return chart; } /** * Creates a panel for the demo (used by SuperDemo.java). * * @return A panel. */ public static JPanel createDemoPanel() { JFreeChart chart = createChart(createDataset()); return new ChartPanel(chart); } /** * Starting point for the demonstration application. * * @param args ignored. */ public static void main(String[] args) { ItemLabelDemo1 demo = new ItemLabelDemo1("Item Label Demo 1"); demo.pack(); RefineryUtilities.centerFrameOnScreen(demo); demo.setVisible(true); } } 86 CHAPTER 12. ITEM LABELS 12.7 Example 2 - Displaying Percentages 12.7.1 Overview 87 In this example, the requirement is to display a bar chart where each bar is labelled with the value represented by the bar and also a percentage (where the percentage is calculated relative to a particular bar within the series OR the total of all the values in the series)—see figure 12.4. Figure 12.4: Percentage item labels In this implementation, the label generator calculates the percentage value on-the-fly. If a category index is supplied in the constructor, the base value used to calculate the percentage is taken from the specified category within the current series. If no category index is available, then the total of all the values in the current series is used as the base. A default percentage formatter is created within the label generator—a more sophisticated implementation would provide the ability for the formatter to be customised via the generator’s constructor. 12.7.2 Source Code The complete source code follows. /* ------------------* ItemLabelDemo2.java * ------------------* (C) Copyright 2005, by Object Refinery Limited. * */ package demo; import java.awt.Color; /** * A simple demo showing a label generator that displays labels that include * a percentage calculation. */ public class ItemLabelDemo2 extends ApplicationFrame { /** * A custom label generator. */ static class LabelGenerator extends AbstractCategoryItemLabelGenerator implements CategoryItemLabelGenerator { /** * The index of the category on which to base the percentage CHAPTER 12. ITEM LABELS * (null = use series total). */ private Integer category; /** A percent formatter. */ private NumberFormat formatter = NumberFormat.getPercentInstance(); /** * Creates a new label generator that displays the item value and a * percentage relative to the value in the same series for the * specified category. * * @param category the category index (zero-based). */ public LabelGenerator(int category) { this(new Integer(category)); } /** * Creates a new label generator that displays the item value and * a percentage relative to the value in the same series for the * specified category. If the category index isnull
, * the total of all items in the series is used. * * @param category the category index (null
permitted). */ public LabelGenerator(Integer category) { super("", NumberFormat.getInstance()); this.category = category; } /** * Generates a label for the specified item. The label is typically * a formatted version of the data value, but any text can be used. * * @param dataset the dataset (null
not permitted). * @param series the series index (zero-based). * @param category the category index (zero-based). * * @return the label (possiblynull
). */ public String generateLabel(CategoryDataset dataset, int series, int category) { String result = null; double base = 0.0; if (this.category != null) { final Number b = dataset.getValue(series, this.category.intValue()); base = b.doubleValue(); } else { base = calculateSeriesTotal(dataset, series); } Number value = dataset.getValue(series, category); if (value != null) { final double v = value.doubleValue(); // you could apply some formatting here result = value.toString() + " (" + this.formatter.format(v / base) + ")"; } return result; } /** * Calculates a series total. * * @param dataset the dataset. * @param series the series index. * * @return The total. */ private double calculateSeriesTotal(CategoryDataset dataset, int series) { double result = 0.0; for (int i = 0; i < dataset.getColumnCount(); i++) { Number value = dataset.getValue(series, i); if (value != null) { result = result + value.doubleValue(); } } 88 CHAPTER 12. ITEM LABELS return result; } } /** * Creates a new demo instance. * * @param title the frame title. */ public ItemLabelDemo2(String title) { super(title); CategoryDataset dataset = createDataset(); JFreeChart chart = createChart(dataset); ChartPanel chartPanel = new ChartPanel(chart); chartPanel.setPreferredSize(new Dimension(500, 270)); setContentPane(chartPanel); } /** * Returns a sample dataset. * * @return the dataset. */ private static CategoryDataset createDataset() { DefaultCategoryDataset dataset = new DefaultCategoryDataset(); dataset.addValue(100.0, "S1", "C1"); dataset.addValue(44.3, "S1", "C2"); dataset.addValue(93.0, "S1", "C3"); dataset.addValue(80.0, "S2", "C1"); dataset.addValue(75.1, "S2", "C2"); dataset.addValue(15.1, "S2", "C3"); return dataset; } /** * Creates a sample chart. * * @param dataset the dataset. * * @return the chart. */ private static JFreeChart createChart(CategoryDataset dataset) { // create the chart... JFreeChart chart = ChartFactory.createBarChart( "Item Label Demo 2", // chart title "Category", // domain axis label "Value", // range axis label dataset, // data PlotOrientation.HORIZONTAL, // orientation true, // include legend true, // tooltips? false // URLs? ); chart.setBackgroundPaint(Color.white); CategoryPlot plot = chart.getCategoryPlot(); plot.setBackgroundPaint(Color.lightGray); plot.setDomainGridlinePaint(Color.white); plot.setRangeGridlinePaint(Color.white); plot.setRangeAxisLocation(AxisLocation.BOTTOM_OR_LEFT); NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis(); rangeAxis.setUpperMargin(0.25); CategoryItemRenderer renderer = plot.getRenderer(); renderer.setItemLabelsVisible(true); // use one or the other of the following lines to see the // different modes for the label generator... renderer.setItemLabelGenerator(new LabelGenerator(null)); //renderer.setLabelGenerator(new LabelGenerator(0)); return chart; 89 CHAPTER 12. ITEM LABELS } /** * Creates a panel for the demo (used by SuperDemo.java). * * @return A panel. */ public static JPanel createDemoPanel() { JFreeChart chart = createChart(createDataset()); return new ChartPanel(chart); } /** * Starting point for the demonstration application. * * @param args ignored. */ public static void main(String[] args) { ItemLabelDemo2 demo = new ItemLabelDemo2("Item Label Demo 2"); demo.pack(); RefineryUtilities.centerFrameOnScreen(demo); demo.setVisible(true); } } 90 Chapter 13 Multiple Axes and Datasets 13.1 Introduction JFreeChart supports the use of multiple axes and datasets in the CategoryPlot and XYPlot classes. You can use this feature to display two or more datasets on a single chart, while making allowance for the fact that the datasets may contain data of vastly different magnitudes—see figure 13.1 for an example. Figure 13.1: A chart with multiple axes Typical charts constructed with JFreeChart use a plot that has a single dataset, a single renderer, a single domain axis and a single range axis. However, it is possible to add multiple datasets, renderers and axes to a plot. In this section, an example is presented showing how to use these additional datasets, renderers and axes. 13.2 An Example 13.2.1 Introduction The MultipleAxisDemo1.java application (included in the JFreeChart Demo distribution) provides a good example of how to create a chart with multiple axes. This section provides some notes on the steps taken within that code. 91 CHAPTER 13. MULTIPLE AXES AND DATASETS 13.2.2 92 Create a Chart To create a chart with multiple axes, datasets, and renderers, you should first create a regular chart (for example, using the ChartFactory class). You can use any chart that is constructed using a CategoryPlot or an XYPlot. In the example, a time series chart is created as follows: XYDataset dataset1 JFreeChart chart = "Multiple Axis "Time of Day", "Primary Range dataset1, true, true, false ); 13.2.3 = createDataset("Series 1", 100.0, new Minute(), 200); ChartFactory.createTimeSeriesChart( Demo 1", Axis", Adding an Additional Axis To add an additional axis to a plot, you can use the setRangeAxis() method: NumberAxis axis2 = new NumberAxis("Range Axis 2"); plot.setRangeAxis(1, axis2); plot.setRangeAxisLocation(1, AxisLocation.BOTTOM OR RIGHT); The setRangeAxis() method is used to add the axis to the plot. Note that an index of 1 (one) has been used—you can add as many additional axes as you require, by incrementing the index each time you add a new axis. The setRangeAxisLocation() method allows you to specify where the axis will appear on the chart, using the AxisLocation class. You can have the axis on the same side as the primary axis, or on the opposite side—the choice is yours. In the example, BOTTOM OR RIGHT is specified, which means (for a range axis) on the right if the plot has a vertical orientation, or at the bottom if the plot has a horizontal orientation. At this point, no additional dataset has been added to the chart, so if you were to display the chart you would see the additional axis, but it would have no data plotted against it. 13.2.4 Adding an Additional Dataset To add an additional dataset to a plot, use the setDataset() method: XYDataset dataset2 = ... // up to you plot.setDataset(1, dataset2); By default, the dataset will be plotted against the primary range axis. To have the dataset plotted against a different axis, use the mapDatasetToDomainAxis() and mapDatasetToRangeAxis() methods. These methods accept two arguments, the first is the index of the dataset, and the second is the index of the axis. 13.2.5 Adding an Additional Renderer When you add an additional dataset, usually it makes sense to add an additional renderer to go with the dataset. Use the setRenderer() method: XYItemRenderer renderer2 = ... // up to you plot.setRenderer(1, renderer2); The index (1 in this case) should correspond to the index of the dataset added previously. Note: if you don’t specify an additional renderer, the primary renderer will be used instead. In that case, the series colors will be shared between the primary dataset and the additional dataset. CHAPTER 13. MULTIPLE AXES AND DATASETS 13.3 93 Hints and Tips When using multiple axes, you need to provide some visual cue to readers to indicate which axis applies to a particular series. In the MultipleAxisDemo1.java application, the color of the axis label text has been changed to match the series color. Additional demos available for download with the JFreeChart Developer Guide include: • DualAxisDemo1.java • DualAxisDemo2.java • DualAxisDemo3.java • DualAxisDemo4.java • MultipleAxisDemo1.java • MultipleAxisDemo2.java • MultipleAxisDemo3.java Chapter 14 Combined Charts 14.1 Introduction JFreeChart supports combined charts via several plot classes that can manage any number of subplots: • CombinedDomainCategoryPlot / CombinedRangeCategoryPlot; • CombinedDomainXYPlot / CombinedRangeXYPlot; This section presents a few examples that use the combined chart facilities provided by JFreeChart. All the examples are included in the JFreeChart demo collection. 14.2 Combined Domain Category Plot 14.2.1 Overview A combined domain category plot is a plot that displays two or more subplots (instances of CategoryPlot) that share a common domain axis. Each subplot maintains its own range axis. An example is shown in figure 14.1. Figure 14.1: A combined domain category plot It is possible to display this chart with a horizontal or vertical orientation—the example shown has a vertical orientation. 94 CHAPTER 14. COMBINED CHARTS 14.2.2 95 Constructing the Chart A demo application (CombinedCategoryPlotDemo1.java, available for download with the JFreeChart Developer Guide) provides an example of how to create this type of chart. The key step is the creation of a CombinedDomainCategoryPlot instance, to which subplots are added: CategoryAxis domainAxis = new CategoryAxis("Category"); CombinedDomainCategoryPlot plot = new CombinedDomainCategoryPlot(domainAxis); plot.add(subplot1, 2); plot.add(subplot2, 1); JFreeChart result = new JFreeChart( "Combined Domain Category Plot Demo", new Font("SansSerif", Font.BOLD, 12), plot, true ); Notice how subplot1 has been added with a weight of 2 (the second argument in the add() method, while subplot2 has been added with a weight of 1. This controls the amount of space allocated to each plot. The subplots are regular CategoryPlot instances that have had their domain axis set to null. For example, in the demo application the following code is used (it includes some customisation of the subplots): CategoryDataset dataset1 = createDataset1(); NumberAxis rangeAxis1 = new NumberAxis("Value"); rangeAxis1.setStandardTickUnits(NumberAxis.createIntegerTickUnits()); LineAndShapeRenderer renderer1 = new LineAndShapeRenderer(); renderer1.setBaseToolTipGenerator(new StandardCategoryToolTipGenerator()); CategoryPlot subplot1 = new CategoryPlot(dataset1, null, rangeAxis1, renderer1); subplot1.setDomainGridlinesVisible(true); CategoryDataset dataset2 = createDataset2(); NumberAxis rangeAxis2 = new NumberAxis("Value"); rangeAxis2.setStandardTickUnits(NumberAxis.createIntegerTickUnits()); BarRenderer renderer2 = new BarRenderer(); renderer2.setBaseToolTipGenerator(new StandardCategoryToolTipGenerator()); CategoryPlot subplot2 = new CategoryPlot(dataset2, null, rangeAxis2, renderer2); subplot2.setDomainGridlinesVisible(true); 14.3 Combined Range Category Plot 14.3.1 Overview A combined range category plot is a plot that displays two or more subplots (instances of CategoryPlot) that share a common range axis. Each subplot maintains its own domain axis. An example is shown in figure 14.2. It is possible to display this chart with a horizontal or vertical orientation (the example above has a vertical orientation). 14.3.2 Constructing the Chart A demo application (CombinedCategoryPlotDemo2.java, available for download with the JFreeChart Developer Guide) provides an example of how to create this type of chart. The key step is the creation of a CombinedRangeCategoryPlot instance, to which subplots are added: ValueAxis rangeAxis = new NumberAxis("Value"); CombinedRangeCategoryPlot plot = new CombinedRangeCategoryPlot(rangeAxis); plot.add(subplot1, 3); plot.add(subplot2, 2); JFreeChart result = new JFreeChart( "Combined Range Category Plot Demo", new Font("SansSerif", Font.BOLD, 12), plot, true ); CHAPTER 14. COMBINED CHARTS 96 Figure 14.2: A combined range category plot. Notice how subplot1 has been added with a weight of 3 (the second argument in the add() method), while subplot2 has been added with a weight of 2. This controls the amount of space allocated to each plot. The subplots are regular CategoryPlot instances that have had their range axis set to null. For example, in the demo application the following code is used (it includes some customisation of the subplots): CategoryDataset dataset1 = createDataset1(); CategoryAxis domainAxis1 = new CategoryAxis("Class 1"); domainAxis1.setCategoryLabelPositions(CategoryLabelPositions.UP 45); domainAxis1.setMaxCategoryLabelWidthRatio(5.0f); LineAndShapeRenderer renderer1 = new LineAndShapeRenderer(); renderer1.setBaseToolTipGenerator(new StandardCategoryToolTipGenerator()); CategoryPlot subplot1 = new CategoryPlot(dataset1, domainAxis1, null, renderer1); subplot1.setDomainGridlinesVisible(true); CategoryDataset dataset2 = createDataset2(); CategoryAxis domainAxis2 = new CategoryAxis("Class 2"); domainAxis2.setCategoryLabelPositions(CategoryLabelPositions.UP 45); domainAxis2.setMaxCategoryLabelWidthRatio(5.0f); BarRenderer renderer2 = new BarRenderer(); renderer2.setBaseToolTipGenerator(new StandardCategoryToolTipGenerator()); CategoryPlot subplot2 = new CategoryPlot(dataset2, domainAxis2, null, renderer2); subplot2.setDomainGridlinesVisible(true); 14.4 Combined Domain XY Plot 14.4.1 Overview A combined domain XY plot is a plot that displays two or more subplots (instances of XYPlot) that share a common domain axis. Each subplot maintains its own range axis. An example is shown in figure 14.3. It is possible to display this chart with a horizontal or vertical orientation (the example shown has a vertical orientation). 14.4.2 Constructing the Chart A demo application (CombinedXYPlotDemo1.java, available for download with the JFreeChart Developer Guide) provides an example of how to create this type of chart. The key step is the creation of a CombinedDomainXYPlot instance, to which subplots are added: CombinedDomainXYPlot plot = new CombinedDomainXYPlot(new NumberAxis("Domain")); plot.setGap(10.0); CHAPTER 14. COMBINED CHARTS 97 Figure 14.3: A combined domain XY plot plot.add(subplot1, 1); plot.add(subplot2, 1); plot.setOrientation(PlotOrientation.VERTICAL); return new JFreeChart( "CombinedDomainXYPlot Demo", JFreeChart.DEFAULT TITLE FONT, plot, true ); Notice how the subplots are added with weights (both 1 in this case). This controls the amount of space allocated to each plot. The subplots are regular XYPlot instances that have had their domain axis set to null. For example, in the demo application the following code is used (it includes some customisation of the subplots): XYDataset data1 = createDataset1(); XYItemRenderer renderer1 = new StandardXYItemRenderer(); NumberAxis rangeAxis1 = new NumberAxis("Range 1"); XYPlot subplot1 = new XYPlot(data1, null, rangeAxis1, renderer1); subplot1.setRangeAxisLocation(AxisLocation.BOTTOM OR LEFT); XYTextAnnotation annotation = new XYTextAnnotation("Hello!", 50.0, 10000.0); annotation.setFont(new Font("SansSerif", Font.PLAIN, 9)); annotation.setRotationAngle(Math.PI / 4.0); subplot1.addAnnotation(annotation); // create subplot 2... XYDataset data2 = createDataset2(); XYItemRenderer renderer2 = new StandardXYItemRenderer(); NumberAxis rangeAxis2 = new NumberAxis("Range 2"); rangeAxis2.setAutoRangeIncludesZero(false); XYPlot subplot2 = new XYPlot(data2, null, rangeAxis2, renderer2); subplot2.setRangeAxisLocation(AxisLocation.TOP OR LEFT); 14.5 Combined Range XY Plot 14.5.1 Overview A combined range XY plot is a plot that displays two or more subplots (instances of XYPlot) that share a common range axis. Each subplot maintains its own domain axis. An example is shown in figure 14.4. It is possible to display this chart with a horizontal or vertical orientation (the example shown has a vertical orientation). CHAPTER 14. COMBINED CHARTS 98 Figure 14.4: A combined range XY plot 14.5.2 Constructing the Chart A demo application (CombinedXYPlotDemo2.java, available for download with the JFreeChart Developer Guide) provides an example of how to create this type of chart. The key step is the creation of a CombinedRangeXYPlot instance, to which subplots are added: // create the plot... CombinedRangeXYPlot plot = new CombinedRangeXYPlot(new NumberAxis("Value")); plot.add(subplot1, 1); plot.add(subplot2, 1); return new JFreeChart( "Combined (Range) XY Plot", JFreeChart.DEFAULT TITLE FONT, plot, true ); Notice how the subplots are added with weights (both 1 in this case). This controls the amount of space allocated to each plot. The subplots are regular XYPlot instances that have had their range axis set to null. For example, in the demo application the following code is used (it includes some customisation of the subplots): // create subplot 1... IntervalXYDataset data1 = createDataset1(); XYItemRenderer renderer1 = new XYBarRenderer(0.20); renderer1.setToolTipGenerator( new StandardXYToolTipGenerator( new SimpleDateFormat("d-MMM-yyyy"), new DecimalFormat("0,000.0") ) ); XYPlot subplot1 = new XYPlot(data1, new DateAxis("Date"), null, renderer1); // create subplot 2... XYDataset data2 = createDataset2(); XYItemRenderer renderer2 = new StandardXYItemRenderer(); renderer2.setToolTipGenerator( new StandardXYToolTipGenerator( new SimpleDateFormat("d-MMM-yyyy"), new DecimalFormat("0,000.0") ) ); XYPlot subplot2 = new XYPlot(data2, new DateAxis("Date"), null, renderer2); Chapter 15 Datasets and JDBC 15.1 Introduction In this section, I describe the use of several datasets that are designed to work with JDBC to obtain data from database tables: • JDBCPieDataset • JDBCCategoryDataset • JDBCXYDataset These datasets have been developed by Bryan Scott of the Australian Antarctic Division. 15.2 About JDBC JDBC is a high-level Java API for working with relational databases. JDBC does a good job of furthering Java’s platform independence, making it possible to write portable code that will work with many different database systems. JDBC provides a mechanism for loading a JDBC driver specific to the database system actually being used. JDBC drivers are available for many databases, on many different platforms. 15.3 Sample Data To see the JDBC datasets in action, you need to create some sample data in a test database. Here is listed some sample data that will be used to create a pie chart, a bar chart and a time series chart. A pie chart will be created using this data (in a table called piedata1): CATEGORY | VALUE ---------+-----London | 54.3 New York | 43.4 Paris | 17.9 Similarly, a bar chart will be created using this data (in a table called categorydata1): CATEGORY | SERIES1 | SERIES2 | SERIES3 ---------+---------+---------+-------London | 54.3 | 32.1 | 53.4 New York | 43.4 | 54.3 | 75.2 Paris | 17.9 | 34.8 | 37.1 99 CHAPTER 15. DATASETS AND JDBC 100 Finally, a time series chart will be generated using this data (in a table called xydata1): X | SERIES1 | SERIES2 | SERIES3 -----------+---------+---------+-------1-Aug-2002 | 54.3 | 32.1 | 53.4 2-Aug-2002 | 43.4 | 54.3 | 75.2 3-Aug-2002 | 39.6 | 55.9 | 37.1 4-Aug-2002 | 35.4 | 55.2 | 27.5 5-Aug-2002 | 33.9 | 49.8 | 22.3 6-Aug-2002 | 35.2 | 48.4 | 17.7 7-Aug-2002 | 38.9 | 49.7 | 15.3 8-Aug-2002 | 36.3 | 44.4 | 12.1 9-Aug-2002 | 31.0 | 46.3 | 11.0 You should set up a test database containing these tables...ask your database administrator to help you if necessary. I’ve called my test database jfreechartdb, but you can change the name if you want to. In the next section I document the steps I used to set up this sample data usingPostgreSQL, the database system that I have available for testing purposes. If you are using a different system, you may need to perform a slightly different procedure—refer to your database documentation for information. 15.4 PostgreSQL 15.4.1 About PostgreSQL PostgreSQL is a powerful object-relational database server, distributed under an open-source licence. You can find out more about PostgreSQL at: http://www.postgresql.org Note: although PostgreSQL is free, it has most of the features of large commercial relational database systems. I encourage you to install it and try it out. 15.4.2 Creating a New Database First, while logged in as the database administrator, I create a test database called jfreechartdb: CREATE DATABASE jfreechartdb; Next, I create a user jfreechart: CREATE USER jfreechart WITH PASSWORD ’password’; This username and password will be used to connect to the database via JDBC. 15.4.3 Creating the Pie Chart Data To create the table for the pie dataset: CREATE TABLE piedata1 ( category VARCHAR(32), value FLOAT ); ...and to populate it: INSERT INTO piedata1 VALUES (’London’, 54.3); INSERT INTO piedata1 VALUES (’New York’, 43.4); INSERT INTO piedata1 VALUES (’Paris’, 17.9); CHAPTER 15. DATASETS AND JDBC 15.4.4 101 Creating the Category Chart Data To create the table for the category dataset: CREATE TABLE category series1 series2 series3 ); categorydata1 ( VARCHAR(32), FLOAT, FLOAT, FLOAT ...and to populate it: INSERT INTO categorydata1 VALUES (’London’, 54.3, 32.1, 53.4); INSERT INTO categorydata1 VALUES (’New York’, 43.4, 54.3, 75.2); INSERT INTO categorydata1 VALUES (’Paris’, 17.9, 34.8, 37.1); 15.4.5 Creating the XY Chart Data To create the table for the XY dataset: CREATE TABLE date series1 series2 series3 ); xydata1 ( DATE, FLOAT, FLOAT, FLOAT ...and to populate it: INSERT INSERT INSERT INSERT INSERT INSERT INSERT INSERT INSERT INTO INTO INTO INTO INTO INTO INTO INTO INTO xydata1 xydata1 xydata1 xydata1 xydata1 xydata1 xydata1 xydata1 xydata1 VALUES VALUES VALUES VALUES VALUES VALUES VALUES VALUES VALUES (’1-Aug-2002’, (’2-Aug-2002’, (’3-Aug-2002’, (’4-Aug-2002’, (’5-Aug-2002’, (’6-Aug-2002’, (’7-Aug-2002’, (’8-Aug-2002’, (’9-Aug-2002’, 54.3, 43.4, 39.6, 35.4, 33.9, 35.2, 38.9, 36.3, 31.0, 32.1, 54.3, 55.9, 55.2, 49.8, 48.4, 49.7, 44.4, 46.3, 53.4); 75.2); 37.1); 27.5); 22.3); 17.7); 15.3); 12.1); 11.0); Granting Table Permissions The last step in setting up the sample database is to grant read access to the new tables to the user jfreechart: GRANT SELECT ON piedata1 TO jfreechart; GRANT SELECT ON categorydata1 TO jfreechart; GRANT SELECT ON xydata1 TO jfreechart; 15.5 The JDBC Driver To access the sample data via JDBC, you need to obtain a JDBC driver for your database. For PostgreSQL, I downloaded a free driver from: http://jdbc.postgresql.org In order to use this driver, I need to ensure that the jar file containing the driver is on the classpath. CHAPTER 15. DATASETS AND JDBC 15.6 The Demo Applications 15.6.1 JDBCPieChartDemo 102 The JDBCPieChartDemo application will generate a pie chart using the data in the piedata1 table, providing that you have configured your database correctly. The code for reading the data is in the readData() method: private PieDataset readData() { JDBCPieDataset data = null; String url = "jdbc:postgresql://nomad/jfreechartdb"; Connection con; try { Class.forName("org.postgresql.Driver"); } catch (ClassNotFoundException e) { System.err.print("ClassNotFoundException: "); System.err.println(e.getMessage()); } try { con = DriverManager.getConnection(url, "jfreechart", "password"); data = new JDBCPieDataset(con); String sql = "SELECT * FROM PIEDATA1;"; data.executeQuery(sql); con.close(); } catch (SQLException e) { System.err.print("SQLException: "); System.err.println(e.getMessage()); } catch (Exception e) { System.err.print("Exception: "); System.err.println(e.getMessage()); } return data; } Important things to note in the code are: • the url used to reference the test database includes the name of my test server (nomad), you will need to modify this; • a connection is made to the database using the username/password combination jfreechart/password; • the query used to pull the data from the database is a standard SELECT query, but you can use any SQL query as long as it returns columns in the required format (refer to the JDBCPieDataset class documentation for details). 15.6.2 JDBCCategoryChartDemo The JDBCCategoryChartDemo application generates a bar chart using the data in the categorydata1 table. The code is almost identical to the JDBCPieChartDemo. Once again, you can use any SQL query as long as it returns columns in the required format (refer to the JDBCCategoryDataset class documentation for details). 15.6.3 JDBCXYChartDemo The JDBCXYChartDemo application generates a time series chart using the data in the xydata1 table. The code is almost identical to the JDBCPieChartDemo. Once again, you can use any SQL query as long as it returns columns in the required format (refer to the JDBCXYDataset class documentation for details). Chapter 16 Exporting Charts to Acrobat PDF 16.1 Introduction In this section, I describe how to export a chart to an Acrobat PDF file using JFreeChart and iText. Along with the description, I provide a small demonstration application that creates a PDF file containing a basic chart. The resulting file can be viewed using Acrobat Reader, or any other software that is capable of reading and displaying PDF files. 16.2 What is Acrobat PDF? Acrobat PDF is a widely used electronic document format. Its popularity is due, at least in part, to its ability to reproduce high quality output on a variety of different platforms. PDF was created by Adobe Systems Incorporated. Adobe provide a free (but closed source) application called Acrobat Reader for reading PDF documents. Acrobat Reader is available on most end-user computing platforms, including GNU/Linux, Windows, Unix, Macintosh and others. If your system doesn’t have Acrobat Reader installed, you can download a copy from: http://www.adobe.com/products/acrobat/readstep.html On some platforms, there are free (in the GNU sense) software packages available for viewing PDF files. Ghostview on Linux is one example. 16.3 iText iText is a popular free Java class library for creating documents in PDF format. It is developed by Bruno Lowagie, Paulo Soares and others. The home page for iText is: http://www.lowagie.com/iText At the time of writing, the latest version of iText is 2.0.1. 16.4 Graphics2D JFreeChart can work easily with iText because iText provides a Graphics2D implementation. Before I proceed to the demonstration application, I will briefly review the Graphics2D class. The java.awt.Graphics2D class, part of the standard Java 2D API, defines a range of methods for drawing text and graphics in a two dimensional space. Particular subclasses of Graphics2D handle all the details of mapping the output (text and graphics) to specific devices. 103 CHAPTER 16. EXPORTING CHARTS TO ACROBAT PDF 104 JFreeChart has been designed to draw charts using only the methods defined by the Graphics2D class. This means that JFreeChart can generate output to any target that can provide a Graphics2D subclass. JFreeChart +draw(Graphics2D) Graphics2D PDF Figure 16.1: The JFreeChart draw() method iText incorporates a PdfGraphics2D class, which means that iText is capable of generating PDF content based on calls to the methods defined by the Graphics2D class...and this makes it easy to produce charts in PDF format, as you will see in the following sections. 16.5 Getting Started To compile and run the demonstration application, you will need the following jar files: File: Description: jfreechart-1.0.9.jar jcommon-1.0.12.jar itext-2.0.1.jar The JFreeChart class library. The JCommon class library (used by JFreeChart). The iText class library. The first two files are included with JFreeChart, and the third is the iText runtime. 16.6 The Application The first thing the sample application needs to do is create a chart. Here we create a time series chart: // create a chart... XYDataset dataset = createDataset(); JFreeChart chart = ChartFactory.createTimeSeriesChart( "Legal & General Unit Trust Prices", "Date", "Price Per Unit", dataset, true, true, false ); // some additional chart customisation here... There is nothing special here—in fact you could replace the code above with any other code that creates a JFreeChart object. You are encouraged to experiment. Next, I will save a copy of the chart in a PDF file: // write the chart to a PDF file... File fileName = new File(System.getProperty("user.home") + "/jfreechart1.pdf"); saveChartAsPDF(fileName, chart, 400, 300, new DefaultFontMapper()); CHAPTER 16. EXPORTING CHARTS TO ACROBAT PDF 105 There are a couple of things to note here. First, I have hard-coded the filename used for the PDF file. I’ve done this to keep the sample code short. In a real application, you would provide some other means for the user to specify the filename, perhaps by presenting a file chooser dialog. Second, the saveChartAsPDF() method hasn’t been implemented yet! To create that method, I’ll first write another more general method, writeChartAsPDF(). This method performs most of the work that will be required by the saveChartAsPDF() method, but it writes data to an output stream rather than a file. public static void writeChartAsPDF(OutputStream out, JFreeChart chart, int width, int height, FontMapper mapper) throws IOException { Rectangle pagesize = new Rectangle(width, height); Document document = new Document(pagesize, 50, 50, 50, 50); try { PdfWriter writer = PdfWriter.getInstance(document, out); document.addAuthor("JFreeChart"); document.addSubject("Demonstration"); document.open(); PdfContentByte cb = writer.getDirectContent(); PdfTemplate tp = cb.createTemplate(width, height); Graphics2D g2 = tp.createGraphics(width, height, mapper); Rectangle2D r2D = new Rectangle2D.Double(0, 0, width, height); chart.draw(g2, r2D); g2.dispose(); cb.addTemplate(tp, 0, 0); } catch (DocumentException de) { System.err.println(de.getMessage()); } document.close(); } Inside this method, you will see some code that sets up and opens an iText document, obtains a Graphics2D instance from the document, draws the chart using the Graphics2D object, and closes the document. You will also notice that one of the parameters for this method is a FontMapper object. The FontMapper interface maps Java Font objects to the BaseFont objects used by iText. The DefaultFontMapper class is predefined with default mappings for the Java logical fonts. If you use only these fonts, then it is enough to create a DefaultFontMapper using the default constructor. If you want to use other fonts (for example, a font that supports a particular character set) then you need to do more work. I’ll give an example of this later. In the implementation of the writeChartAsPDF() method, I’ve chosen to create a PDF document with a custom page size (matching the requested size of the chart). You can easily adapt the code to use a different page size, alter the size and position of the chart and even draw multiple charts inside one PDF document. Now that I have a method to send PDF data to an output stream, it is straightforward to implement the saveChartAsPDF() method. Simply create a FileOutputStream and pass it on to the writeChartAsPDF() method: public static void saveChartAsPDF(File file, JFreeChart chart, int width, int height, FontMapper mapper) throws IOException { OutputStream out = new BufferedOutputStream(new FileOutputStream(file)); writeChartAsPDF(out, chart, width, height, mapper); out.close(); } CHAPTER 16. EXPORTING CHARTS TO ACROBAT PDF 106 This is all the code that is required. The pieces can be assembled into the following program (reproduced in full here so that you can see all the required import statements and the context in which the code is run): /* ------------------* PDFExportDemo1.java * ------------------* (C) Copyright 2002-2005, by Object Refinery Limited. * */ package demo.pdf; import import import import import import import import java.awt.Graphics2D; java.awt.geom.Rectangle2D; java.io.BufferedOutputStream; java.io.File; java.io.FileOutputStream; java.io.IOException; java.io.OutputStream; java.text.SimpleDateFormat; import import import import import import import import import org.jfree.chart.ChartFactory; org.jfree.chart.JFreeChart; org.jfree.chart.axis.DateAxis; org.jfree.chart.plot.XYPlot; org.jfree.chart.renderer.xy.XYLineAndShapeRenderer; org.jfree.data.time.Month; org.jfree.data.time.TimeSeries; org.jfree.data.time.TimeSeriesCollection; org.jfree.data.xy.XYDataset; import import import import import import import import com.lowagie.text.Document; com.lowagie.text.DocumentException; com.lowagie.text.Rectangle; com.lowagie.text.pdf.DefaultFontMapper; com.lowagie.text.pdf.FontMapper; com.lowagie.text.pdf.PdfContentByte; com.lowagie.text.pdf.PdfTemplate; com.lowagie.text.pdf.PdfWriter; /** * A simple demonstration showing how to write a chart to PDF format using * JFreeChart and iText. ** You can download iText from http://www.lowagie.com/iText. */ public class PDFExportDemo1 { /** * Saves a chart to a PDF file. * * @param file the file. * @param chart the chart. * @param width the chart width. * @param height the chart height. */ public static void saveChartAsPDF(File file, JFreeChart chart, int width, int height, FontMapper mapper) throws IOException { OutputStream out = new BufferedOutputStream(new FileOutputStream(file)); writeChartAsPDF(out, chart, width, height, mapper); out.close(); } /** * Writes a chart to an output stream in PDF format. * * @param out the output stream. * @param chart the chart. * @param width the chart width. * @param height the chart height. * */ public static void writeChartAsPDF(OutputStream out, JFreeChart chart, CHAPTER 16. EXPORTING CHARTS TO ACROBAT PDF int width, int height, FontMapper mapper) throws IOException { Rectangle pagesize = new Rectangle(width, height); Document document = new Document(pagesize, 50, 50, 50, 50); try { PdfWriter writer = PdfWriter.getInstance(document, out); document.addAuthor("JFreeChart"); document.addSubject("Demonstration"); document.open(); PdfContentByte cb = writer.getDirectContent(); PdfTemplate tp = cb.createTemplate(width, height); Graphics2D g2 = tp.createGraphics(width, height, mapper); Rectangle2D r2D = new Rectangle2D.Double(0, 0, width, height); chart.draw(g2, r2D); g2.dispose(); cb.addTemplate(tp, 0, 0); } catch (DocumentException de) { System.err.println(de.getMessage()); } document.close(); } /** * Creates a dataset, consisting of two series of monthly data. * * * * @return the dataset. */ public static XYDataset createDataset() { TimeSeries s1.add(new s1.add(new s1.add(new s1.add(new s1.add(new s1.add(new s1.add(new s1.add(new s1.add(new s1.add(new s1.add(new s1.add(new s1.add(new s1.add(new s1.add(new s1.add(new s1.add(new s1.add(new s1 = new TimeSeries("L&G European Index Trust", Month.class); Month(2, 2001), 181.8); Month(3, 2001), 167.3); Month(4, 2001), 153.8); Month(5, 2001), 167.6); Month(6, 2001), 158.8); Month(7, 2001), 148.3); Month(8, 2001), 153.9); Month(9, 2001), 142.7); Month(10, 2001), 123.2); Month(11, 2001), 131.8); Month(12, 2001), 139.6); Month(1, 2002), 142.9); Month(2, 2002), 138.7); Month(3, 2002), 137.3); Month(4, 2002), 143.9); Month(5, 2002), 139.8); Month(6, 2002), 137.0); Month(7, 2002), 132.8); TimeSeries s2.add(new s2.add(new s2.add(new s2.add(new s2.add(new s2.add(new s2.add(new s2.add(new s2.add(new s2.add(new s2.add(new s2.add(new s2.add(new s2.add(new s2.add(new s2.add(new s2.add(new s2.add(new s2 = new TimeSeries("L&G UK Index Trust", Month.class); Month(2, 2001), 129.6); Month(3, 2001), 123.2); Month(4, 2001), 117.2); Month(5, 2001), 124.1); Month(6, 2001), 122.6); Month(7, 2001), 119.2); Month(8, 2001), 116.5); Month(9, 2001), 112.7); Month(10, 2001), 101.5); Month(11, 2001), 106.1); Month(12, 2001), 110.3); Month(1, 2002), 111.7); Month(2, 2002), 111.0); Month(3, 2002), 109.6); Month(4, 2002), 113.2); Month(5, 2002), 111.6); Month(6, 2002), 108.8); Month(7, 2002), 101.6); TimeSeriesCollection dataset = new TimeSeriesCollection(); dataset.addSeries(s1); dataset.addSeries(s2); return dataset; } public static void main(String[] args) { try { 107 CHAPTER 16. EXPORTING CHARTS TO ACROBAT PDF 108 // create a chart... XYDataset dataset = createDataset(); JFreeChart chart = ChartFactory.createTimeSeriesChart( "Legal & General Unit Trust Prices", "Date", "Price Per Unit", dataset, true, true, false ); // some additional chart customisation here... XYPlot plot = chart.getXYPlot(); XYLineAndShapeRenderer renderer = (XYLineAndShapeRenderer) plot.getRenderer(); renderer.setShapesVisible(true); DateAxis axis = (DateAxis) plot.getDomainAxis(); axis.setDateFormatOverride(new SimpleDateFormat("MMM-yyyy")); // write the chart to a PDF file... File fileName = new File(System.getProperty("user.home") + "/jfreechart1.pdf"); saveChartAsPDF(fileName, chart, 400, 300, new DefaultFontMapper()); } catch (IOException e) { System.out.println(e.getMessage()); } } } Before you compile and run the application, remember to change the file name used for the PDF file to something appropriate for your system! And include the jar files listed in section 16.5 on your classpath. 16.7 Viewing the PDF File After compiling and running the sample application, you can view the resulting PDF file using a PDF viewer like Acrobat Reader (or, in my case, Gnome PDF Viewer): Most PDF viewer applications provide zooming features that allow you to get a close up view of your charts. 16.8 Unicode Characters It is possible to use the full range of Unicode characters in JFreeChart and iText, as long as you are careful about which fonts you use. In this section, I present some modifications to the previous example to show how to do this. CHAPTER 16. EXPORTING CHARTS TO ACROBAT PDF 16.8.1 109 Background Internally, Java uses the Unicode character encoding to represent text strings. This encoding uses sixteen bits per character, which means there are potentially 65,536 different characters available (the Unicode standard defines something like 38,000 characters). You can use any of these characters in both JFreeChart and iText, subject to one proviso: the font you use to display the text must define the characters used or you will not be able to see them. Many fonts are not designed to display the entire Unicode character set. The following website contains useful information about fonts that do support Unicode (at least to some extent): http://www.slovo.info/unifonts.htm I have tried out the tahoma.ttf font with success. In fact, I will use this font in the example that follows. The Tahoma font doesn’t support every character defined in Unicode, so if you have specific requirements then you need to choose an appropriate font. At one point I had the Arial Unicode MS font (arialuni.ttf) installed on my system—this has support for the full Unicode character set, although this means that the font definition file is quite large (around 24 megabytes!) 16.8.2 Fonts, iText and Java iText has to handle fonts according to the PDF specification. This deals with document portability by allowing fonts to be (optionally) embedded in a PDF file. This requires access to the font definition file. Java, on the other hand, abstracts away some of the details of particular font formats with the use of the Font class. To support the Graphics2D implementation in iText, it is necessary to map Font objects from Java to BaseFont objects in iText. This is the role of the FontMapper interface. If you create a new DefaultFontMapper instance using the default constructor, it will already contain sensible mappings for the logical fonts defined by the Java specification. But if you want to use additional fonts—and you must if you want to use a wide range of Unicode characters—then you need to add extra mappings to the DefaultFontMapper object. 16.8.3 Mapping Additional Fonts I’ve decided to use the Tahoma font to display a chart title that incorporates some Unicode characters. The font definition file (tahoma.ttf) is located, on my system, in the directory: /opt/sun-jdk-1.4.2.08/jre/lib/fonts Here’s the code used to create the FontMapper for use by iText—I’ve based this on an example written by Paulo Soares: DefaultFontMapper mapper = new DefaultFontMapper(); mapper.insertDirectory("/opt/sun-jdk-1.4.2.08/jre/lib/fonts"); DefaultFontMapper.BaseFontParameters pp = mapper.getBaseFontParameters("Tahoma"); if (pp!=null) { pp.encoding = BaseFont.IDENTITY_H; } Now I can modify the code that creates the chart, in order to add a custom title to the chart (I’ve changed the data and chart type also): // create a chart... TimeSeries series = new TimeSeries("Random Data"); Day current = new Day(1, 1, 2000); double value = 100.0; for (int i = 0; i < 1000; i++) { try { value = value + Math.random() - 0.5; CHAPTER 16. EXPORTING CHARTS TO ACROBAT PDF 110 series.add(current, new Double(value)); current = (Day) current.next(); } catch (SeriesException e) { System.err.println("Error adding to series"); } } XYDataset data = new TimeSeriesCollection(series); JFreeChart chart = ChartFactory.createTimeSeriesChart( "Test", "Date", "Value", data, true, false, false ); // Unicode test... String text = "\u278A\u20A0\u20A1\u20A2\u20A3\u20A4\u20A5\u20A6\u20A7\u20A8\u20A9"; //String text = "hi"; Font font = new Font("Tahoma", Font.PLAIN, 12); TextTitle subtitle = new TextTitle(text, font); chart.addSubtitle(subtitle); Notice that the subtitle (a random collection of currency symbols) is defined using escape sequences to specify each Unicode character. This avoids any problems with encoding conversions when I save the Java source file. The output from the modified sample program is shown in figure 16.2. The example has been embedded in this document in PDF format, so it is a good example of the type of output you can expect by following the instructions in this document. Test 102.5 100.0 Value 97.5 95.0 92.5 90.0 87.5 85.0 Jan-2000 Jul-2000 Jan-2001 Jul-2001 Jan-2002 Date Random Data Figure 16.2: A Unicode subtitle Jul-2002 Chapter 17 Exporting Charts to SVG Format 17.1 Introduction In this section, I present an example that shows how to export charts to SVG format, using JFreeChart and Batik (an open source library for working with SVG). 17.2 Background 17.2.1 What is SVG? Scalable Vector Graphics (SVG) is a standard language for describing two-dimensional graphics in XML format. It is a Recommendation of the World Wide Web Consortium (W3C). 17.2.2 Batik Batik is an open source toolkit, written in Java, that allows you to generate SVG content. Batik is available from: http://xml.apache.org/batik At the time of writing, the latest stable version of Batik is 1.6. 17.3 A Sample Application 17.3.1 JFreeChart and Batik JFreeChart and Batik can work together relatively easily because: • JFreeChart draws all chart output using Java’s Graphics2D abstraction; and • Batik provides a concrete implementation of Graphics2D that generates SVG output (SVGGraphics2D). In this section, a simple example is presented to get you started using JFreeChart and Batik. The example is based on the technique described here: http://xml.apache.org/batik/svggen.html 111 CHAPTER 17. EXPORTING CHARTS TO SVG FORMAT 17.3.2 112 Getting Started First, you should download Batik and install it according to the instructions provided on the Batik web page. To compile and run the sample program presented in the next section, you need to ensure that the following jar files are on your classpath: File: Description: jcommon-1.0.12.jar jfreechart-1.0.9.jar batik-awt-util.jar batik-dom.jar batik-svggen.jar batik-util.jar Common classes from JFree. The JFreeChart class library. Batik runtime files. Batik runtime files. Batik runtime files. Batik runtime files. 17.3.3 The Application Create a project in your favourite Java development environment, add the libraries listed in the previous section, and type in the following program (or easier, grab a copy of the source from the JFreeChart demo collection): /* -----------------* SVGExportDemo.java * -----------------* (C) Copyright 2002-2005, by Object Refinery Limited. * */ package demo.svg; import import import import import import java.awt.geom.Rectangle2D; java.io.File; java.io.FileOutputStream; java.io.IOException; java.io.OutputStreamWriter; java.io.Writer; import import import import import import import org.apache.batik.dom.GenericDOMImplementation; org.apache.batik.svggen.SVGGraphics2D; org.jfree.chart.ChartFactory; org.jfree.chart.JFreeChart; org.jfree.data.general.DefaultPieDataset; org.w3c.dom.DOMImplementation; org.w3c.dom.Document; /** * A demonstration showing the export of a chart to SVG format. */ public class SVGExportDemo { /** * Starting point for the demo. * * @param args ignored. */ public static void main(String[] args) throws IOException { // create a dataset... DefaultPieDataset data = new DefaultPieDataset(); data.setValue("Category 1", new Double(43.2)); data.setValue("Category 2", new Double(27.9)); data.setValue("Category 3", new Double(79.5)); // create a chart JFreeChart chart = ChartFactory.createPieChart( "Sample Pie Chart", data, true, false, false ); // THE FOLLOWING CODE BASED ON THE EXAMPLE IN THE BATIK DOCUMENTATION... // Get a DOMImplementation CHAPTER 17. EXPORTING CHARTS TO SVG FORMAT 113 DOMImplementation domImpl = GenericDOMImplementation.getDOMImplementation(); // Create an instance of org.w3c.dom.Document Document document = domImpl.createDocument(null, "svg", null); // Create an instance of the SVG Generator SVGGraphics2D svgGenerator = new SVGGraphics2D(document); // set the precision to avoid a null pointer exception in Batik 1.5 svgGenerator.getGeneratorContext().setPrecision(6); // Ask the chart to render into the SVG Graphics2D implementation chart.draw(svgGenerator, new Rectangle2D.Double(0, 0, 400, 300), null); // Finally, stream out SVG to a file using UTF-8 character to // byte encoding boolean useCSS = true; Writer out = new OutputStreamWriter( new FileOutputStream(new File("test.svg")), "UTF-8"); svgGenerator.stream(out, useCSS); } } Running this program creates a file test.svg in SVG format. 17.3.4 Viewing the SVG Batik includes a viewer application (“Squiggle”) which you can use to open and view the SVG file. The Batik download includes instructions for running the viewer, effectively all you require is: java -jar batik-squiggle.jar The following screen shot shows the pie chart that we created earlier, displayed using the browser application. A transformation (rotation) has been applied to the chart from within the browser: If you play about with the viewer, zooming in and out and applying various transformations to the chart, you will begin to appreciate the power of the SVG format. Chapter 18 Applets 18.1 Introduction Subject to a couple of provisos, using JFreeChart in an applet is relatively straightforward. This section provides a brief overview of the important issues and describes a working example that should be sufficient to get you started. Figure 18.1: An applet using JFreeChart Figure 18.1 shows a sample applet that uses JFreeChart. This applet is available online at: http://www.object-refinery.com/jfreechart/applet.html The source code for this applet appears later in this section. 18.2 Issues The main issues to consider when developing applets (whether with or without JFreeChart) are: • browser support; • security restrictions; • code size. Be sure that you understand these issues before you commit significant resources to writing applets. 114 CHAPTER 18. APPLETS 18.2.1 115 Browser Support The vast majority of web browsers provide support for the latest version of Java (JDK 1.5.0) and will therefore have no problems running applets that use JFreeChart (recall that JFreeChart will run on any version of the JDK from 1.3.1 onwards). However, the vast majority of users on the web use (by default in most cases) the one web browser— Microsoft Internet Explorer (MSIE)—that only supports a version of Java (JDK 1.1) that is now hopelessly out-of-date. This is a problem, because applets that use JFreeChart will not work on a default installation of MSIE. There is a workaround—users can download and install Sun’s Java plugin—but, like many workarounds, it is too much effort and inconvenience for many people. The end result is a deployment problem for developers who choose to write applets. This single issue has caused many developers to abandon their plans to develop applets1 and instead choose an easier-to-deploy technology such as Java Servlets (see the next chapter). 18.2.2 Security Applets (and Java more generally) have been designed with security in mind. When an applet runs in your web browser, it is restricted in the operations that it is permitted to perform. For example, an applet typically will not be allowed to read or write to the local filesystem. Describing the details of Java’s security mechanism is beyond the scope of this text, but you should be aware that some functions provided by JFreeChart (for example, the option to save charts to PNG format via the pop-up menu) will not work in applets that are subject to the default security policy. If you need these functions to work, then you will need to study Java’s security mechanism in more detail. 18.2.3 Code Size A final issue to consider is the size of the “runtime” code required for your applet. Before an applet can run, the code (typically packed into jar files) has to be downloaded to the end user’s computer. Clearly, for users with limited bandwidth connections, the size of the code can be an issue. The JFreeChart code is distributed in a jar file that is around 1,000KB in size. That isn’t large— especially when you consider the number and variety of charts that JFreeChart supports—but, at the same time, it isn’t exactly optimal for a user on a dial-up modem connection. And you need to add to that the JCommon jar file (around 290KB) plus whatever code you have for your applet. As always with JFreeChart, you have the source code so you could improve this by repackaging the JFreeChart jar file to include only those classes that are used by your applet (directly or indirectly). 18.3 A Sample Applet As mentioned in the introduction, a sample applet that uses JFreeChart can be seen at the following URL:2 http://www.object-refinery.com/jfreechart/applet.html Two aspects of the sample applet are interesting, the source code that is used to create the applet and the HTML file that is used to invoke the applet. 1 For some people this issue won’t be a concern. For example, you may be developing applets for internal corporate use, and your standard desktop configuration includes a browser that supports JDK 1.5.0. Alternatively, you may be providing an applet for public use via the World Wide Web, but it is not critical that every user be able to run the applet. 2 If the applet does not work for you, please check that your web browser is configured correctly and supports JDK 1.3.1 or later. CHAPTER 18. APPLETS 18.3.1 116 The HTML The HTML used to invoke the applet is important, since it needs to reference the necessary jar files. The HTML applet tag used is: Notice that three jar files are referenced. The first contains the applet class (source code in the next section) only, while the remaining two jar files are the standard JFreeChart and JCommon class libraries (the version numbers reflect the age of the demo rather than the current releases). You can place the applet tag anywhere in your HTML file that you might place some other element (such as an image). 18.3.2 The Source Code The sample applet is created using the following source code (which is included in the “support demos” package). There is very little applet-specific code here—we just extend JApplet: /* -----------* Applet1.java * -----------* (C) Copyright 2002-2005, by Object Refinery Limited. */ package demo.applet; import import import import java.awt.BasicStroke; java.awt.Color; java.awt.event.ActionEvent; java.awt.event.ActionListener; import javax.swing.JApplet; import javax.swing.Timer; import import import import import import import import import import org.jfree.chart.ChartPanel; org.jfree.chart.JFreeChart; org.jfree.chart.axis.DateAxis; org.jfree.chart.axis.NumberAxis; org.jfree.chart.plot.XYPlot; org.jfree.chart.renderer.xy.XYItemRenderer; org.jfree.chart.renderer.xy.XYLineAndShapeRenderer; org.jfree.data.time.Millisecond; org.jfree.data.time.TimeSeries; org.jfree.data.time.TimeSeriesCollection; /** * A simple applet demo. */ public class Applet1 extends JApplet { /** Time series for total memory used. */ private TimeSeries total; /** Time series for free memory. */ private TimeSeries free; /** * Creates a new instance. */ public Applet1() { // create two series that automatically discard data more than // 30 seconds old... this.total = new TimeSeries("Total", Millisecond.class); this.total.setMaximumItemAge(30000); this.free = new TimeSeries("Free", Millisecond.class); this.free.setMaximumItemAge(30000); TimeSeriesCollection dataset = new TimeSeriesCollection(); dataset.addSeries(total); dataset.addSeries(free); CHAPTER 18. APPLETS DateAxis domain = new DateAxis("Time"); NumberAxis range = new NumberAxis("Memory"); XYItemRenderer renderer = new XYLineAndShapeRenderer(true, false); XYPlot plot = new XYPlot(dataset, domain, range, renderer); plot.setBackgroundPaint(Color.lightGray); plot.setDomainGridlinePaint(Color.white); plot.setRangeGridlinePaint(Color.white); renderer.setSeriesPaint(0, Color.red); renderer.setSeriesPaint(1, Color.green); renderer.setSeriesStroke(0, new BasicStroke(1.5f)); renderer.setSeriesStroke(1, new BasicStroke(1.5f)); domain.setAutoRange(true); domain.setLowerMargin(0.0); domain.setUpperMargin(0.0); domain.setTickLabelsVisible(true); range.setStandardTickUnits(NumberAxis.createIntegerTickUnits()); JFreeChart chart = new JFreeChart( "Memory Usage", JFreeChart.DEFAULT_TITLE_FONT, plot, true ); chart.setBackgroundPaint(Color.white); ChartPanel chartPanel = new ChartPanel(chart); chartPanel.setPopupMenu(null); getContentPane().add(chartPanel); new Applet1.DataGenerator().start(); } /** * Adds an observation to the ’total memory’ time series. * * @param y the total memory used. */ private void addTotalObservation(double y) { total.add(new Millisecond(), y); } /** * Adds an observation to the ’free memory’ time series. * * @param y the free memory. */ private void addFreeObservation(double y) { free.add(new Millisecond(), y); } /** * The data generator. */ class DataGenerator extends Timer implements ActionListener { /** * Constructor. */ DataGenerator() { super(100, null); addActionListener(this); } /** * Adds a new free/total memory reading to the dataset. * * @param event the action event. */ public void actionPerformed(ActionEvent event) { long f = Runtime.getRuntime().freeMemory(); long t = Runtime.getRuntime().totalMemory(); addTotalObservation(t); addFreeObservation(f); } } } 117 Chapter 19 Servlets 19.1 Introduction The Java Servlets API is a popular technology for creating web applications. JFreeChart is well suited for use in a servlet environment and, in this section, some examples are presented to help those developers that are interested in using JFreeChart for web applications. All the sample code in this section is available for download from: http://www.object-refinery.com/jfreechart/premium/index.html The file to download is jfreechart-1.0.9-demo.zip.1 19.2 A Simple Servlet The ServletDemo1 class implements a very simple servlet that returns a PNG image of a bar chart generated using JFreeChart. When it is run, the servlet will return a raw image to the client (web browser) which will display the image without any surrounding HTML—see figure 19.1. Typically, Figure 19.1: ServletDemo1 in a browser you will not present raw output in this way, so this servlet is not especially useful on its own, but the example is: 1 To access this page you need to enter the username and password provided to you in the confirmation e-mail you received when you purchased the JFreeChart Developer Guide. 118 CHAPTER 19. SERVLETS 119 • a good illustration of the request-response nature of servlets; • useful as a test case if you are configuring a server environment and want to check that everything is working. We will move on to a more complex example later, showing how to request different charts using HTML forms, and embedding the generated charts within HTML output. Here is the code for the basic servlet: /* ----------------* ServletDemo1.java * ----------------* (C) Copyright 2002-2004, by Object Refinery Limited. * */ package demo; import java.io.IOException; import java.io.OutputStream; import import import import javax.servlet.ServletException; javax.servlet.http.HttpServlet; javax.servlet.http.HttpServletRequest; javax.servlet.http.HttpServletResponse; import import import import import org.jfree.chart.ChartFactory; org.jfree.chart.ChartUtilities; org.jfree.chart.JFreeChart; org.jfree.chart.plot.PlotOrientation; org.jfree.data.category.DefaultCategoryDataset; /** * A basic servlet that returns a PNG image file generated by JFreeChart. * This class is described in the JFreeChart Developer Guide in the * "Servlets" chapter. */ public class ServletDemo1 extends HttpServlet { /** * Creates a new demo. */ public ServletDemo1() { // nothing required } /** * Processes a GET request. * * @param request the request. * @param response the response. * * @throws ServletException if there is a servlet related problem. * @throws IOException if there is an I/O problem. */ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { OutputStream out = response.getOutputStream(); try { DefaultCategoryDataset dataset = new DefaultCategoryDataset(); dataset.addValue(10.0, "S1", "C1"); dataset.addValue(4.0, "S1", "C2"); dataset.addValue(15.0, "S1", "C3"); dataset.addValue(14.0, "S1", "C4"); dataset.addValue(-5.0, "S2", "C1"); dataset.addValue(-7.0, "S2", "C2"); dataset.addValue(14.0, "S2", "C3"); dataset.addValue(-3.0, "S2", "C4"); dataset.addValue(6.0, "S3", "C1"); dataset.addValue(17.0, "S3", "C2"); dataset.addValue(-12.0, "S3", "C3"); dataset.addValue( 7.0, "S3", "C4"); dataset.addValue(7.0, "S4", "C1"); dataset.addValue(15.0, "S4", "C2"); dataset.addValue(11.0, "S4", "C3"); dataset.addValue(0.0, "S4", "C4"); dataset.addValue(-8.0, "S5", "C1"); CHAPTER 19. SERVLETS 120 dataset.addValue(-6.0, "S5", "C2"); dataset.addValue(10.0, "S5", "C3"); dataset.addValue(-9.0, "S5", "C4"); dataset.addValue(9.0, "S6", "C1"); dataset.addValue(8.0, "S6", "C2"); dataset.addValue(null, "S6", "C3"); dataset.addValue(6.0, "S6", "C4"); dataset.addValue(-10.0, "S7", "C1"); dataset.addValue(9.0, "S7", "C2"); dataset.addValue(7.0, "S7", "C3"); dataset.addValue(7.0, "S7", "C4"); dataset.addValue(11.0, "S8", "C1"); dataset.addValue(13.0, "S8", "C2"); dataset.addValue(9.0, "S8", "C3"); dataset.addValue(9.0, "S8", "C4"); dataset.addValue(-3.0, "S9", "C1"); dataset.addValue(7.0, "S9", "C2"); dataset.addValue(11.0, "S9", "C3"); dataset.addValue(-10.0, "S9", "C4"); JFreeChart chart = ChartFactory.createBarChart( "Bar Chart", "Category", "Value", dataset, PlotOrientation.VERTICAL, true, true, false ); response.setContentType("image/png"); ChartUtilities.writeChartAsPNG(out, chart, 400, 300); } catch (Exception e) { System.err.println(e.toString()); } finally { out.close(); } } } The doGet() method is called by the servlet engine when a request is made by a client (usually a web browser). In response to the request, the servlet performs several steps: • an OutputStream reference is obtained for returning output to the client; • a chart is created; • the content type for the response is set to image/png. This tells the client what type of data it is receiving; • a PNG image of the chart is written to the output stream; • the output stream is closed. 19.3 Compiling the Servlet Note that the classes in the javax.servlet.* package (and sub-packages), used by the demo servlet, are not part of the Java 2 Standard Edition (J2SE). In order to compile the above code using J2SE, you will need to obtain a servlet.jar file. I’ve used the one that is redistributed with Tomcat (an open source servlet engine written using Java). You can find out more about Tomcat at: http://tomcat.apache.org/ You will also require the JFreeChart and JCommon jar files to compile the above servlet. Change your working directory to jfreechart-1.0.9-demo, then enter the following command (on Windows, you need to change the colons to semi-colons, and the forward slashes to backward slashes): javac -classpath jfreechart-1.0.9.jar:lib/jcommon-1.0.12.jar:lib/servlet.jar source/demo/ServletDemo1.java CHAPTER 19. SERVLETS 121 This should create a ServletDemo1.class file. The next section describes how to deploy this servlet using Tomcat. 19.4 Deploying the Servlet Servlets are deployed in the webapps directory provided by your servlet engine. In my case, I am using Tomcat 5.5.15 on Ubuntu Linux 5.10, and the directory is:2 /home/dgilbert/apache-tomcat-5.5.15/webapps Within the webapps directory, create a jfreechart1 directory to hold the first servlet demo, then create the following structure within the directory: .../jfreechart1/WEB-INF/web.xml .../jfreechart1/WEB-INF/lib/jfreechart-1.0.9.jar .../jfreechart1/WEB-INF/lib/jcommon-1.0.12.jar .../jfreechart1/WEB-INF/classes/demo/ServletDemo1.class You need to create the web.xml file—it provides information about the servlet:
Once you have all these files in place, restart your servlet engine and type in the following URL using your favourite web browser: http://localhost:8080/jfreechart1/servlet/ServletDemo1 If all is well, you will see the chart image displayed in your browser, as shown in figure 19.1. 19.5 Embedding Charts in HTML Pages It is possible to embed a chart image generated by a servlet inside an HTML page (that is generated by another servlet). This is demonstrated by ServletDemo2, which is also available in the jfreechart-1.0.9-demo.zip file. ServletDemo2 processes a request by returning a page of HTML that, in turn, references another servlet (ServletDemo2ChartGenerator) that returns a PNG image of a chart. The end result is a chart embedded in an HTML page, as shown in figure 19.2. Here is the code for ServletDemo2: 2 Servlets are portable between different servlet engines, so if you are using a different servlet engine, consult the documentation to find the location of the webapps folder. CHAPTER 19. SERVLETS 122 Figure 19.2: ServletDemo2 in a browser /* ----------------* ServletDemo2.java * ----------------* (C) Copyright 2002-2004, by Object Refinery Limited. * */ package demo; import java.io.IOException; import java.io.PrintWriter; import import import import javax.servlet.ServletException; javax.servlet.http.HttpServlet; javax.servlet.http.HttpServletRequest; javax.servlet.http.HttpServletResponse; /** * A basic servlet that generates an HTML page that displays a chart generated by * JFreeChart. * ServletDemo1 demo.ServletDemo1 ServletDemo1 /servlet/ServletDemo1 * This servlet uses another servlet (ServletDemo2ChartGenerator) to create a PNG image * for the embedded chart. *
* This class is described in the JFreeChart Developer Guide. */ public class ServletDemo2 extends HttpServlet { /** * Creates a new servlet demo. */ public ServletDemo2() { // nothing required } /** * Processes a POST request. *
* The chart.html page contains a form for generating the first request, after that * the HTML returned by this servlet contains the same form for generating subsequent * requests. * * @param request the request. * @param response the response. * * @throws ServletException if there is a servlet related problem. * @throws IOException if there is an I/O problem. */ public void doPost(HttpServletRequest request, HttpServletResponse response) CHAPTER 19. SERVLETS 123 throws ServletException, IOException { PrintWriter out = new PrintWriter(response.getWriter()); try { String param = request.getParameter("chart"); response.setContentType("text/html"); out.println(""); out.println("
"); out.println("JFreeChart Servlet Demo 2 "); out.println(""); out.println(""); out.println("JFreeChart Servlet Demo
"); out.println(""); out.println("Please choose a chart type:"); out.println("
"); out.println(""); out.println(""); out.println(""); out.flush(); out.close(); } catch (Exception e) { System.err.println(e.toString()); } finally { out.close(); } } } Notice how this code gets a reference to a Writer from the response parameter, rather than an OutputStream as in the previous example. The reason for this is because this servlet will be returning text (HTML), compared to the previous servlet which returned binary data (a PNG image).3 The response type is set to text/html since this servlet returns HTML text. An important point to note is that the tag in the HTML references another servlet (ServletDemo2ChartGenerator), and this other servlet creates the required chart image. The actual chart returned is controlled by the chart parameter, which is set up in the HTML using a
This second HTML page contains a