scrollable charts
scrollable charts
Can anyone give guidance for creating scrollable charts? For example, I want to create a dynamic gantt chart application with a timeline that spans 24 hours, but with only 4 hours worth of activities visible at a time. The chart would scroll dynamically as time passes.
Re: scrollable charts
I am currently working on adding scrolling features to the library; the main problem is that the chart is drawn as a graphics object. This could be put into a scrollpanel, but then u scroll the entire chart, axes, titles, legend, etc as well. I currently have a test application which redraws the entire graph every time a scroll bar is moved; it works, but is pretty slow (it is just bareable on an 800MHz machine). If you want a copy of this email me; I'm currently working on a faster version and will probably add this to the distribution once it is stable-ish.
As for scrolling as time passes, add a Listener to the dataset (or something of that sort) so that it will scroll to the right most point whenever the data changes. (but this could be dangerous; the scenario I am thinking of is if the user is scrolling around on the data when a new bit of data comes in; they will be thrown to the end of the data; this could be avoided with the dataset Listener checking to see if scrolling is happening before updating the display; or alternately with the use of a timeout - if x minutes have passed since the last user-scroll then shift the chart to the right most point).
As for scrolling as time passes, add a Listener to the dataset (or something of that sort) so that it will scroll to the right most point whenever the data changes. (but this could be dangerous; the scenario I am thinking of is if the user is scrolling around on the data when a new bit of data comes in; they will be thrown to the end of the data; this could be avoided with the dataset Listener checking to see if scrolling is happening before updating the display; or alternately with the use of a timeout - if x minutes have passed since the last user-scroll then shift the chart to the right most point).
Re: scrollable charts
I implemented 2 sliders below the x-axis.
1. slider1 is for the startposition of the origin of the x-axis.
2. slider2 is for the range displayed on the x-axis.
Here is the test-program :
import com.jrefinery.chart.*;
import com.jrefinery.chart.demo.*;
import com.jrefinery.chart.tooltips.*;
import com.jrefinery.data.*;
import com.jrefinery.ui.*;
import java.awt.*;
import java.util.*;
import javax.swing.*;
import javax.swing.event.*;
public class Test
{
JSlider sliderStart;
JSlider sliderRange;
NumberAxis xAxis;
NumberAxis yAxis;
TestDataset data;
XYPlot plot;
public Test()
{
}
private void doIt()
{
String title;
String domain;
String range;
JFrame frame;
JFreeChart chart;
TestDatasetThread update;
JPanel sliderPanel;
title = "Dynamic Chart";
domain = "Domain";
range = "Range";
data = new TestDataset();
xAxis = new HorizontalNumberAxis(domain);
xAxis.setAutoRange(false);
xAxis.setRange(0, 10.0);
yAxis = new VerticalNumberAxis(range);
plot = new XYPlot(data, xAxis, yAxis);
plot.setXYItemRenderer(
new StandardXYItemRenderer(StandardXYItemRenderer.LINES,
new StandardXYToolTipGenerator()));
chart = new JFreeChart(title, JFreeChart.DEFAULT_TITLE_FONT, plot, true);
/*
update = new TestDatasetThread(data);
update.setTime(1000);
*/
sliderPanel = new JPanel(new GridLayout(0, 1));
sliderStart = new JSlider(JSlider.HORIZONTAL);
sliderRange = new JSlider(JSlider.HORIZONTAL);
sliderPanel.add(sliderStart);
sliderPanel.add(sliderRange);
sliderRange.setMinimum(0);
sliderRange.setMaximum(100);
sliderRange.setValue(
(int)(xAxis.getMaximumAxisValue() - xAxis.getMinimumAxisValue()));
sliderRange.addChangeListener(new XAxisRangeListener());
XAxisStartListener xAxisStartListener;
xAxisStartListener = new XAxisStartListener();
sliderStart.addChangeListener(xAxisStartListener);
sliderStart.setMinimum(0);
sliderStart.setMaximum(100);
data.addChangeListener(xAxisStartListener);
frame = new JFrame("Test");
frame.getContentPane().add(BorderLayout.CENTER, new ChartPanel(chart));
frame.getContentPane().add(BorderLayout.SOUTH, sliderPanel);
frame.pack();
frame.show();
Thread thread = new Thread(update);
thread.start();
}
class XAxisRangeListener implements ChangeListener
{
public void stateChanged(ChangeEvent e)
{
if (sliderRange.getValueIsAdjusting())
return;
xAxis.setMaximumAxisValue(
xAxis.getMinimumAxisValue() + sliderRange.getValue());
}
}
class XAxisStartListener implements ChangeListener, DatasetChangeListener
{
public void stateChanged(ChangeEvent e)
{
int value;
Range dataRange;
Range chartRange;
double chartUpper;
double chartLower;
double dataUpper;
double dataLower;
double chartSize;
double dataSize;
if (sliderStart.getValueIsAdjusting())
return;
value = sliderStart.getValue();
chartRange = xAxis.getRange();
dataRange = ((HorizontalValuePlot)plot).getHorizontalDataRange();
dataLower = dataRange.getLowerBound();
dataUpper = dataRange.getUpperBound();
chartLower = chartRange.getLowerBound();
chartUpper = chartRange.getUpperBound();
chartSize = chartUpper - chartLower;
chartLower = dataLower + (value * (dataUpper - dataLower) / 100.0);
xAxis.setRange(chartLower, chartLower + chartSize);
}
public void datasetChanged(DatasetChangeEvent event)
{
Range dataRange;
Range chartRange;
double chartLower;
double chartUpper;
double dataLower;
double dataUpper;
double chartSize;
double dataSize;
int value;
if (sliderStart.getValueIsAdjusting())
return;
chartRange = xAxis.getRange();
dataRange = ((HorizontalValuePlot)plot).getHorizontalDataRange();
dataLower = dataRange.getLowerBound();
dataUpper = dataRange.getUpperBound();
chartLower = chartRange.getLowerBound();
dataSize = dataUpper - dataLower;
if (dataSize != 0.0)
value = (int) (((chartLower - dataLower) / dataSize) * 100.0);
else
value = 100;
if (value < 0.0)
value = 100;
if (!sliderStart.getValueIsAdjusting())
{
sliderStart.removeChangeListener(this);
sliderStart.setValue(value);
sliderStart.addChangeListener(this);
}
}
}
public static void main(String[] args)
{
try
{
new Test().doIt();
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
}
1. slider1 is for the startposition of the origin of the x-axis.
2. slider2 is for the range displayed on the x-axis.
Here is the test-program :
import com.jrefinery.chart.*;
import com.jrefinery.chart.demo.*;
import com.jrefinery.chart.tooltips.*;
import com.jrefinery.data.*;
import com.jrefinery.ui.*;
import java.awt.*;
import java.util.*;
import javax.swing.*;
import javax.swing.event.*;
public class Test
{
JSlider sliderStart;
JSlider sliderRange;
NumberAxis xAxis;
NumberAxis yAxis;
TestDataset data;
XYPlot plot;
public Test()
{
}
private void doIt()
{
String title;
String domain;
String range;
JFrame frame;
JFreeChart chart;
TestDatasetThread update;
JPanel sliderPanel;
title = "Dynamic Chart";
domain = "Domain";
range = "Range";
data = new TestDataset();
xAxis = new HorizontalNumberAxis(domain);
xAxis.setAutoRange(false);
xAxis.setRange(0, 10.0);
yAxis = new VerticalNumberAxis(range);
plot = new XYPlot(data, xAxis, yAxis);
plot.setXYItemRenderer(
new StandardXYItemRenderer(StandardXYItemRenderer.LINES,
new StandardXYToolTipGenerator()));
chart = new JFreeChart(title, JFreeChart.DEFAULT_TITLE_FONT, plot, true);
/*
update = new TestDatasetThread(data);
update.setTime(1000);
*/
sliderPanel = new JPanel(new GridLayout(0, 1));
sliderStart = new JSlider(JSlider.HORIZONTAL);
sliderRange = new JSlider(JSlider.HORIZONTAL);
sliderPanel.add(sliderStart);
sliderPanel.add(sliderRange);
sliderRange.setMinimum(0);
sliderRange.setMaximum(100);
sliderRange.setValue(
(int)(xAxis.getMaximumAxisValue() - xAxis.getMinimumAxisValue()));
sliderRange.addChangeListener(new XAxisRangeListener());
XAxisStartListener xAxisStartListener;
xAxisStartListener = new XAxisStartListener();
sliderStart.addChangeListener(xAxisStartListener);
sliderStart.setMinimum(0);
sliderStart.setMaximum(100);
data.addChangeListener(xAxisStartListener);
frame = new JFrame("Test");
frame.getContentPane().add(BorderLayout.CENTER, new ChartPanel(chart));
frame.getContentPane().add(BorderLayout.SOUTH, sliderPanel);
frame.pack();
frame.show();
Thread thread = new Thread(update);
thread.start();
}
class XAxisRangeListener implements ChangeListener
{
public void stateChanged(ChangeEvent e)
{
if (sliderRange.getValueIsAdjusting())
return;
xAxis.setMaximumAxisValue(
xAxis.getMinimumAxisValue() + sliderRange.getValue());
}
}
class XAxisStartListener implements ChangeListener, DatasetChangeListener
{
public void stateChanged(ChangeEvent e)
{
int value;
Range dataRange;
Range chartRange;
double chartUpper;
double chartLower;
double dataUpper;
double dataLower;
double chartSize;
double dataSize;
if (sliderStart.getValueIsAdjusting())
return;
value = sliderStart.getValue();
chartRange = xAxis.getRange();
dataRange = ((HorizontalValuePlot)plot).getHorizontalDataRange();
dataLower = dataRange.getLowerBound();
dataUpper = dataRange.getUpperBound();
chartLower = chartRange.getLowerBound();
chartUpper = chartRange.getUpperBound();
chartSize = chartUpper - chartLower;
chartLower = dataLower + (value * (dataUpper - dataLower) / 100.0);
xAxis.setRange(chartLower, chartLower + chartSize);
}
public void datasetChanged(DatasetChangeEvent event)
{
Range dataRange;
Range chartRange;
double chartLower;
double chartUpper;
double dataLower;
double dataUpper;
double chartSize;
double dataSize;
int value;
if (sliderStart.getValueIsAdjusting())
return;
chartRange = xAxis.getRange();
dataRange = ((HorizontalValuePlot)plot).getHorizontalDataRange();
dataLower = dataRange.getLowerBound();
dataUpper = dataRange.getUpperBound();
chartLower = chartRange.getLowerBound();
dataSize = dataUpper - dataLower;
if (dataSize != 0.0)
value = (int) (((chartLower - dataLower) / dataSize) * 100.0);
else
value = 100;
if (value < 0.0)
value = 100;
if (!sliderStart.getValueIsAdjusting())
{
sliderStart.removeChangeListener(this);
sliderStart.setValue(value);
sliderStart.addChangeListener(this);
}
}
}
public static void main(String[] args)
{
try
{
new Test().doIt();
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
}
Re: scrollable charts
Thanks for your answers. Would you send me your test application? That might help me to see how its done and what kind of performance I can expect.
Thanks Again,
Sue McClain
Thanks Again,
Sue McClain