Tuesday, June 9, 2009

Creating Charts in JavaFX

Note: This entry is an excerpt from the upcoming "Pro JavaFX Platform" book written by Jim Weaver, Stephen Chin, Weiqi Gao, and myself. You can find out more by clicking on the book image to the right of this page. -- Dean The chart components included in JavaFX give developers an easy way to let the users of their applications visualize a wide variety of data. There are six kinds of charts supported in JavaFX 1.2:
  • An Area Chart displays quantitative data like a line chart but with the area between the line and the horizontal axis shaded. Good for comparing the magnitude of two or more series of data.
  • The Bar Chart is a good way to show data in a way that makes it easy to see how the data changes over time or under a set of different conditions. The data is represented as rectangular area or, in the case of a 3D chart, a cubic volume whose height corresponds to the value of the data point being displayed.
  • Bubble Charts plot data points on a 2-dimensional grid and have the extra ability to display the relative magnitudes of the data by controlling the diameter of the point (or bubble) displayed at each XY coordinate.
  • A Line Chart is a simple way to display 2-dimensional data points where each point is connected to the next point in the data series by a line.
  • Pie Charts are typically used to display the relative percentages of a series of values on a circle. The value of each piece of data, as a percentage of the total, dictates how much of the circle’s area it takes up. In other words, the chart shows how big a slice of the pie each value represents.
  • The Scatter Chart is used to plot the points of one or more series of data. These charts are typically used to show the correlation (or not) of the data by comparing how the data points are clustered (or not).
One of these things is not like the others. Other than the pie chart, all of these charts are meant to handle 2-dimensional data points as pairs of XY coordinates. The class hierarchy, shown below, of the chart components in the javafx.scene.chart package reflects this fact. The ChartDemo program, which is included with the Chapter 5 examples and is shown below, displays an example of each of these types of charts. In the next sections we’ll take a look at how to use each of these different charts and the many different ways that they can be customized.
Click the image to launch the demo
Common Chart Properties The Chart abstract base class contains several public variables that are common to all charts. One such property that all charts share is a title. The following public variables in the Chart class control the style, position, and content of the title displayed on a chart.
  • title is a String whose contents will be displayed as the title of the chart. Setting this variable to null or an empty string (its default value) causes the chart to be rendered without a title.
  • titleFill controls the fill color of the title text. Since it is of type Paint, it can be a solid color as well as a linear or radial gradient.
  • titleFont allows you to set the Font to be used to render the title text.
  • titleGap is a Number that specifies the number of pixels to leave as a gap between the title and the content of the chart.
  • titleSide is an enumeration that specifies which side of the chart the title will appear on. Its type is javafx.scene.chart.part.Side and its possible values are TOP, BOTTOM, LEFT, and RIGHT.
All charts are also capable of displaying a legend. The legend is very useful when your charts are displaying more than one data series. It allows the user to easily see which of the plotted data points belongs to each of the data series. The public variables below affect how the legend is presented on a chart.
  • legendGap is a Number that specifies the number of pixels to leave as a gap between the legend and the content of the chart.
  • legendSide specifies which side of the chart the legend will appear on. Like titleSide, the possible values are TOP, BOTTOM, LEFT, and RIGHT.
  • legendVisible is a Boolean value that controls whether the legend will be shown on the chart or hidden.
The Chart class also has a public-read variable named legend that provides a reference to the actual Legend object used by the chart. This object can be used to customize many aspects of the legend and will be discussed later in the section on customization. Pie Chart Getting a basic pie chart on the screen is very straightforward. All you really need is a sequence of PieChart.Data objects and a title string. For each value that you want to display in your pie chart you just create a PieChart.Data object and supply the value and a text string to use as the label for the value. The sequence of data objects is then used in the pie chart’s declaration. Since every chart is-a Node, you can just insert the chart into your scene graph in order to display it. The listing below demonstrates how to create and display a PieChart. Notice that we have used the titleFont variable to make the chart’s title stand out a little more. The source code is from PieChartIntro.fx, which can be found in the ChartIntro example project.
Stage {
  title: "Pie Chart"
  scene: Scene {
    content: [
      PieChart {
        title: "What Is Your Favorite Pie?"
        titleFont: Font { size: 24 }
        data: [
          PieChart.Data {
            value: 21
            label: "Pumpkin"
          }
          PieChart.Data {
            value: 33
            label: "Apple"
          }
          PieChart.Data {
            value: 17
            label: "Cherry"
          }
          PieChart.Data {
            value: 29
            label: "3.14159"
          }
        ]
      }
    ]
  }
}
This chart is rendered as shown in the image below. Note that right out of the box, the charts have a modern look with lighting and shading effects baked right in. You can also see that by default the title appears at the top of the chart. If you prefer a more 3-dimensional look to your pie charts, you can use the PieChart3D class instead of a PieChart. Everything in the listing above (aside from the class name) can remain the same and the result will have the appearance of a 3-dimensional disk instead of a circle. That concludes this entry. In the next entry, I'll continue this excerpt by taking a closer look at XYCharts.

22 comments:

  1. Great article, great demo. Thank you, Dean.

    ReplyDelete
  2. The demo produces this error on Mac OS X 10.5.7 with J2SE 5.0 on 32-bit Intel:

    An error occurred while launching/running the application.

    Title: ChartDemo
    Vendor: dean
    Category: Download Error

    Bad MIME type returned from server when accessing resource: http://idisk.mac.com/driverson/Public/jnlp/ChartDemo.jnlp - null

    JNLPException[category: Download Error : Exception: null : LaunchDesc: null ]
    at com.sun.javaws.cache.DownloadProtocol.doDownload(DownloadProtocol.java:656)
    at com.sun.javaws.cache.DownloadProtocol.isLaunchFileUpdateAvailable(DownloadProtocol.java:819)
    at com.sun.javaws.LaunchDownload.getUpdatedLaunchDesc(LaunchDownload.java:135)
    at com.sun.javaws.Launcher.downloadResources(Launcher.java:1037)
    at com.sun.javaws.Launcher.handleApplicationDesc(Launcher.java:378)
    at com.sun.javaws.Launcher.handleLaunchFile(Launcher.java:218)
    at com.sun.javaws.Launcher.run(Launcher.java:165)
    at java.lang.Thread.run(Thread.java:613)

    ReplyDelete
  3. Patrick,

    Is the error repeatable? I'm wondering if it's just Apple's servers being flaky or a real problem on 32-bit Macs. I know it works on 10.5.7 with 64-bit Macs (what I'm running). Unfortunately, I don't have access to a 32-bit platform at the moment.

    Dean

    ReplyDelete
  4. Can I use this Chart API in normal Java program too?

    ReplyDelete
  5. Dean, great article! Are the Chart examples included within the ebook pre-release (Alpha Book) of the Pro JavaFx Platform book?

    Tom

    ReplyDelete
  6. @tsjung75: There has been some work done in the latest version of JFXtras by Jim Clark to embed a JavaFX scene in a JComponent. Generally speaking, it's much easier to embed Java in a JavaFX program though.

    @Tom All examples from the book will be released when the book is finished. Probably some time in the next two weeks I would guess.

    ReplyDelete
  7. Dean,

    Yes, the problem is repeatable on my 32-bit Intel Mac. But the demo works fine on my Debian 5.0 Linux and Windows XP machines. I do not have a 64-bit Mac. Cleaning both my browser and Web Start caches did not help. I'm guessing that Apple should set the MIME type for .jnlp files to "application/x-java-jnlp-file" on their idisk.mac.com servers so my old J2SE 5.0 Web Start can recognize them. It would be even better if Apple updated Java on 32-bit Intel Macs to SE 6.

    Patrick

    ReplyDelete
  8. Has anyone looked at dynamic charts?

    http://forums.sun.com/thread.jspa?threadID=5390747&tstart=0

    ReplyDelete
  9. This comment has been removed by the author.

    ReplyDelete
  10. "Unable to launch the application." on Windows7RC with JDK 6 Update 14 installed.

    Stacktrace;
    java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at com.sun.javaws.Launcher.executeApplication(Unknown Source)
    at com.sun.javaws.Launcher.executeMainClass(Unknown Source)
    at com.sun.javaws.Launcher.doLaunchApp(Unknown Source)
    at com.sun.javaws.Launcher.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)

    Caused by: java.lang.NoClassDefFoundError: com/sun/javafx/runtime/Main
    at com.sun.javafx.runtime.main.Main.main(Main.java:35)
    ... 9 more

    Caused by: java.lang.ClassNotFoundException: com.sun.javafx.runtime.Main
    at java.net.URLClassLoader$1.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(Unknown Source)
    at com.sun.jnlp.JNLPClassLoader.findClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    at java.lang.ClassLoader.loadClassInternal(Unknown Source)
    ... 10 more

    ReplyDelete
  11. Apple's Java for Mac OS X 10.5 Update 4 fixes the problems that I reported above. I can run the demo from the command line like this:
    javaws ~/Desktop/ChartDemo.jnlp

    Unfortunately, the update removes the ability to launch Web Start from the Finder. So the command line is the only way to run jnlp files. Clicking on a Web Start file annoyingly opens it in Dashcode. I assume this problem is only on 32-bit Intel Macs.

    ReplyDelete
  12. After installing Java for Mac OS X 10.5 Update 4, Java Web Start.app an be found in /System/Library/CoreServices/

    To restore correct Web Start behavior, do a Get Info on any jnlp file and choose to open it with the Java Web Start.app

    The demo on this web page will then launch when clicked! :)

    ReplyDelete
  13. The charts look fine, but is there a support for using date axis? All the examples use number axis, and the API doesn't look to contain support for date.

    Any ideas?

    ReplyDelete
  14. I particularly like any form of UML class diagrams to explain the relationship between classes.

    Thanks!
    Rob Wilson.

    ReplyDelete
  15. ntimesc
    where can i get the source code of this chardemo.jnpl .... plz ???

    ReplyDelete
  16. The code is available on the jfxtras.org community site along with all of the other examples from the book:

    http://jfxtras.org/portal/pro-javafx-platform/-/asset_publisher/1Bl5/content/15695?redirect=%2Fportal%2Fpro-javafx-platform

    ReplyDelete
  17. I am new to JavaFX. our requirement is how to embed JavaFX charts in a Java Web Application.To be precise,How to use JavaFX charts in a web based Business Intelligence(BI) report/dashboard.I was trying to achieve since last 3days.Any help will be appreciated.

    Thanks in advance

    ReplyDelete
  18. I just work with charts in JavaFX. They are impressive, but I don't know how to export chart to a bitmap and save it as a file. Is it possible? It is very important fo me. I tried to find an answer in web and in books bot... nothing.

    ReplyDelete
  19. Hello..

    I am new to JavaFX. is it possible to pass a HashMap/ArrayList to JavaFX from Javascript???

    Thanks in advance

    ReplyDelete
  20. how did u display gridlines in the background of each chart.

    can u post some sample piece of code.

    thanks
    uday

    ReplyDelete
  21. When I use JFXtras to embed the charts into a swing JComponent, the charts lose all layout. The chart width and heights are always correct but all the chart content is smushed up into the corner of the scene with no width and height. Did you happen to try to put the ChartDemo into a swing component?

    ReplyDelete
  22. nice but not much use for me ... no DateAxis !!!
    wait and see , maybe FX 3.0

    ReplyDelete

Please Note: All comments are moderated. That's why you won't see your comment appear right away. If it's not some stupid piece of spam, it will appear soon.

Note: Only a member of this blog may post a comment.