JFreeChart: Add and sync a srollbar when zooming a chart (Eclipse plugin / SWT)
Asked Answered
D

2

1

I am using JFreeChart library to plot something in an Eclipse view and currently my code for view initialization looks as follows:

@Override
public void createPartControl(Composite parent)
{
    JFreeChart chart = null;

    // Created via different object     
    chart = graph.createLineChart("Test Graph", "x", "y");

    ChartComposite frame = new ChartComposite(parent, SWT.NONE, chart, true);
    frame.setRangeZoomable(false);      
    parent.layout(true);
}

I wanted to add scrolling to my graph when the user zooms in, but so far all the examples that I found (in the demo package, here, and other sources) are based on Swing dealing with JPanes and ChartPanels.

How can I achieve the same in the createPartControl() function of my view where I have only a Composite. Is it possible to do it in SWT only or should I mix (need to figure out how) SWT with SWING or AWT?

Thank you

Dentilingual answered 2/12, 2011 at 19:55 Comment(2)
To use JFreeChart with SWT: https://mcmap.net/q/1021776/-jfreechart-with-swt Alternatives to JFreeChart: #23316Jurat
@vanaprogeja Actually I have found a way to avoid SWT_AWT bridge for this need. I am busy right now but when I finish the project, I'll post some code here for future referenceDentilingual
R
2

You might look at SlidingXYDataset, mentioned here, or the paging approach shown here.

Redd answered 2/12, 2011 at 21:42 Comment(2)
After a while I gave up on using this approach. It's a good solution, but for my use case I ran into some inconveniences. You can check my answer bellow to see what I am referring to. Also my answer includes code on how to use a slider with JFreeChart in SWT.Dentilingual
I must admit though, that you links were a very good starting pointDentilingual
D
3

In addition to the accepted answer I'd like to post an answer myself, because I ran into a couple of issues regarding to SlidingXYDataset:

  1. The implementation allows to specify the number of points in the dataset that can be shown at any given time and that is OK for most use cases. But in the case where the data points are sparsed very uniformly in the dataset sliding thorugh data will cause the domain axis to change its range.
    For example if the window size is 5 datapoints and first 5 are 2 units appart and the next 5 are 20 units appart the X axis visible range size will change when your are sliding.
    So you can see what the behaviour will look like when all the points are ploted at arbitrary locations. This may or may not be a desired behaviour. In my case I needed to have a fixed visible range of the X axis (for example 200 units) and to keep it as such all the time.

  2. For some reason I was not able to create a SlidingXYDataset by giving it an empty XYSeriesCollection/TimeSeriesCollection. I needed to start with an empty dataset and update it in real time and I had to add useless data to start with. But that's maybe because I was doing something wrong.


Having said that above, there might be workarounds for it, but I went and implemented the zooming and scrollbar in a different than the accepted answer's way.

Also this example shows how to sync the slider when user performs a zoom action on the graph.


First: you need to create an XYLineChart and set the desired range (The example is elaborated for X axis only, but can be applied for Y axis as well)

XYSeries dataset = new XYSeries("my dataset");
XYSeriesCollection datasetCollection = new XYSeriesCollection(dataset);
JFreeChart chart = ChartFactory.createXYLineChart("title", 
                   "x label", 
                   "y label", 
                   datasetCollection, 
                   PlotOrientation.VERTICAL, 
                   true, false, false);

XYPlot plot = chart.getXYPlot();
ValueAxis domainAxis = plot.getDomainAxis();
ValueAxis rangeAxis  = plot.getRangeAxis();

domainAxis.setAutoRange(false);
domainAxis.setFixedAutoRange(300); // 300 units visible at anytime on X axis
domainAxis.setLowerBound(0); // start from 0


Second: you need to put both the chart and a scroll bar inside the parent layout. In SWT you can do this for example through the user of FormLayout

// Given that composite is the parent Composite
FormLayout layout = new FormLayout();
composite.setLayout(layout);

chartComposite = new ChartComposite(composite, SWT.NONE, chart, true);
Slider slider = new Slider(composite, SWT.NONE);
sldier.setValues(/* depends on your needs */);

// add the slider to the bottom of the form
FormData sliderLayoutData = new FormData();
sliderLayoutData.left = new FormAttachment(0,0);
sliderLayoutData.bottom = new FormAttachment(100,0);
sliderLayoutData.right = new FormAttachment(100,0);
slider.setLayoutData(sliderLayoutData);

// now add the graphComposite to the form above the slider
FormData graphLayoutData = new FormData();
graphLayoutData.left = new FormAttachment(0,0);
graphLayoutData.right = new FormAttachment(100,0);
graphLayoutData.top = new FormAttachment(0,0);
graphLayoutData.bottom = new FormAttachment(slider);      
chartComposite.setLayoutData(graphLayoutData);    

// refresh the layout
composite.layout(true);

Now every time you move the slider, you need to capture that event and change the chart's domain range with the to methods according to you slider data:

  domainAxis.setLowerBound(minimum visible);
  domainAxis.setUpperBound(maximum visible);


Third: Finaly you need to override the zoom method of the ChartComposite either by extending this object or right above when you create a new one

@Override 
public void zoom(Rectangle selection)
{
  XYPlot plot = (XYPlot) getChart().getPlot();
  Rectangle2D plotArea = new Rectangle2D.Double( getScreenDataArea().x,
          getScreenDataArea().y,
          getScreenDataArea().width,
          getScreenDataArea().height);

  float x1 = (float) plot.getDomainAxis().
                       java2DToValue(selection.x, 
                                     plotArea, 
                                     plot.getDomainAxisEdge());

  float x2 = (float) plot.getDomainAxis().
                       java2DToValue(selection.x + selection.width, 
                                     plotArea, 
                                     plot.getDomainAxisEdge());

  // x1 and x2 will have the points transalted into chart coordinates
    // of the selection the user made for zooming the X axis  
  // you can adjust your chart to show only the selected (zoomed) 
    // information as such
  domainAxis.setLowerBound(x1);
  domainAxis.setUpperBound(x2);

  // and now adjust the slider information so it's 
    // synced to your graph's current view
  sldier.setValues(/* depends on your needs */);
}

Hope this implementation can find it's use in other people's use cases.

Dentilingual answered 11/1, 2012 at 18:39 Comment(0)
R
2

You might look at SlidingXYDataset, mentioned here, or the paging approach shown here.

Redd answered 2/12, 2011 at 21:42 Comment(2)
After a while I gave up on using this approach. It's a good solution, but for my use case I ran into some inconveniences. You can check my answer bellow to see what I am referring to. Also my answer includes code on how to use a slider with JFreeChart in SWT.Dentilingual
I must admit though, that you links were a very good starting pointDentilingual

© 2022 - 2024 — McMap. All rights reserved.