1

I'd like to make a JFreeChart Histogram that maintains a constant number of bins while zooming in and out. For example, maybe zoomed way out you can see 12 years, and there would be 1 bin for each year. When you zoom in a little more you might see 12 months and there would be a bin for each month. Zooming in even further maybe there are 1 bin for each day, each hour, etc. They don't have to be such clean bin sizes, but you get the idea.

I'm using HistogramDataset.addSeries to add my data to the histogram. The bins parameter, is the number of bins for the entire set and doesn't take zooming into consideration.

I've observed that I can use a ChartPanel and override its zoom method. In here I could potentially alter the number of bins. However, I'm having a hard time figuring out where I can alter the number of bins and what it should be altered to.

EDIT:

There are a few parts of this problem that I am interested in that I believe are critical to a solution:

  1. How best to tell that the user has zoomed. My current approach is to override zoom.
  2. How to determine the bounds that the user has zoomed to. I'm still not sure how to do this.
  3. How to change the number of bins in the data model so that zooming maintains the same number of shown bins.

For some context, my end goal is to create a Google finance style control: Google Finance style control for Java?

Community
  • 1
  • 1
Luke
  • 3,742
  • 4
  • 31
  • 50

2 Answers2

2

Overloading the zoom feature is appealing, but perhaps confusing. As an alternative, consider adding a control that updates the data model, as shown in this example. Instances of an enum are particularly convenient for populating a JComboBox, as shown here.

Community
  • 1
  • 1
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
  • I'm not sure I completely understand what you're suggesting here. I could add another control, but I don't want to if I don't have to. Why make the user do 2 things (zoom and change a combo box) when they could just do 1 (zoom)? Let's say I'm showing a histogram with data from 2001 through 2011 with 10 bins, then the user zooms in on April 2003 through June 2003. The resulting data set will show only 1 bin (if any). I'd like to break it down into 10 *new* bins. I'm not sure how either of those examples help me handle that zoom case and solve the problem. Maybe I'm missing something. – Luke May 17 '12 at 12:33
  • No, your understanding is correct; the examples are only relevant to the alternative I suggest. In either case, you'll need to update the model, whether that update is controlled by a combo or a zoom gesture. I'd develop the underlying functionality first, then expose it using the simpler approach first. – trashgod May 17 '12 at 17:32
1

To answer my individual questions above:

  1. I continued to override zoom on the ChartPanel class.
  2. In order to determine the range that the user zoomed to I used the windowToRatio and ratioToModel functions below, as the zoom function is given window coordinates.
  3. To change the number of bins, I actually kept the number of bins the same and simply changed the dataset passed into the chart. I used a SortedMap for my data model that I could easily get subMap's from.

Functions:

private double windowToRatio(double window) {
    Rectangle2D scaledDataArea = getScreenDataArea();
    return (window - scaledDataArea.getMinX()) / scaledDataArea.getWidth();
}

private double ratioToModel(double ratio) {
    Range domainRange = getChart().getXYPlot().getDomainAxis().getRange();
    return domainRange.getLowerBound() + ratio * domainRange.getLength();
}
Luke
  • 3,742
  • 4
  • 31
  • 50