Hi folks,
I am trying to implement a scrollbar on a line chart. I am using a JScrollBar and that part is working fine. My question is in regards to understanding the interplay between the Range, the upper and lower bounds of the dataset, etc.
If the highest X value in my XYDataset is 200 and the lowest is -200, is it possible to have the visible X-Axis show 0 - 200 but then the scrollbar could enable the user to scroll to the left to see the negative X-Values?
In my chart even when I my dataset includes negative numbers it just shows the values in the dataset from 0 and above. I can post the code if someone has the time to look but just thought maybe someone might be able to give me a verbal pointer.
Thank you in advance.
Understanding Visible Domain Range
Skunk,
Thank you for your quick reponse.
I kind of understand what you are saying. The problem I see is when my chart is created, lets say x data ranges from -200 to 200. The domain axis always shows that full range, ie starting x tickmark at -200 and last x tickmark at 200. Now say I fix the charts domain range at 0, 200. Then visually on the chart you only see 0 - 200 on the axis. If I then get the upper and lower bounds of the chart the values are 0 and 200. This is where I get confused, shouldn't the the value that getLowerBounds() returns be the lowest value in my x dataset, in my case -200?
If you can offer any help I'd really appreciate it. Also if you could explain a little more what you meant by mapping the data indices to the JScrollBar that would be very helpful.
Thanks in advance.
Thank you for your quick reponse.
I kind of understand what you are saying. The problem I see is when my chart is created, lets say x data ranges from -200 to 200. The domain axis always shows that full range, ie starting x tickmark at -200 and last x tickmark at 200. Now say I fix the charts domain range at 0, 200. Then visually on the chart you only see 0 - 200 on the axis. If I then get the upper and lower bounds of the chart the values are 0 and 200. This is where I get confused, shouldn't the the value that getLowerBounds() returns be the lowest value in my x dataset, in my case -200?
If you can offer any help I'd really appreciate it. Also if you could explain a little more what you meant by mapping the data indices to the JScrollBar that would be very helpful.
Thanks in advance.
-
- Posts: 1634
- Joined: Sat Feb 17, 2007 1:51 pm
A chart has no upper or lower bound, but an axis has. These bounds can either be calculated by JFreeChart based on the values in the dataset or manually set by the user.cobragtk wrote:If I then get the upper and lower bounds of the chart ...
The value range in the dataset is independent from these bounds. If you want to get the x value range of an XYDataset, try DatasetUtilities.findDomainBounds(XYDataset set).
Visible range
In your case 0...200
The whole datarange for all mapped datasets (useful if you have more than one dataset)
In your case -200...200
Code: Select all
xyplot.getDomainAxis().getRange()
The whole datarange for all mapped datasets (useful if you have more than one dataset)
Code: Select all
xyplot.getDataRange( xyplot.getDomainAxis() )
Paradoxoff and mkivinie thank you for your help.
My chart is working now including the scrolling, so thank you. I am still having difficulty understanding the relationship between moving my JScrollBar and how my XYDataSet, specifically the domain values will be moved by the scroll bar. I feel stupid. For example I create a JScrollBar like so:
JScrollBar scrollBar = new JScrollBar(JScrollBar.HORIZONTAL,0,0,0,100);
The chart is set to calculate the range automatically, and subsequently it does. I see -200 up to 200 represented on the domain axis as ticks. Now when the scroll bar moves and an AdjustmentEvent is fired, I simply set the domain range to be from:
(domainAxis lowerBound + amount scrollbar moved) TO (domainAxis upperBound + amount scrollbar moved)
This works fine but I don't understand how to correctly relate the dataset values to how much I should adjust the scroll bar. Currently my dataset consists of just integer values for the domain axis values, that is why I speculate that it is working fine. I just want to understand so that if I need to change my domain axis values to be hours or days I can implement the scrolling accordingly.
I have posted my test class below for people to reference. Thanks in advance.
My chart is working now including the scrolling, so thank you. I am still having difficulty understanding the relationship between moving my JScrollBar and how my XYDataSet, specifically the domain values will be moved by the scroll bar. I feel stupid. For example I create a JScrollBar like so:
JScrollBar scrollBar = new JScrollBar(JScrollBar.HORIZONTAL,0,0,0,100);
The chart is set to calculate the range automatically, and subsequently it does. I see -200 up to 200 represented on the domain axis as ticks. Now when the scroll bar moves and an AdjustmentEvent is fired, I simply set the domain range to be from:
(domainAxis lowerBound + amount scrollbar moved) TO (domainAxis upperBound + amount scrollbar moved)
This works fine but I don't understand how to correctly relate the dataset values to how much I should adjust the scroll bar. Currently my dataset consists of just integer values for the domain axis values, that is why I speculate that it is working fine. I just want to understand so that if I need to change my domain axis values to be hours or days I can implement the scrolling accordingly.
I have posted my test class below for people to reference. Thanks in advance.
Code: Select all
public class ScrollingLineChart extends JFrame implements AdjustmentListener{
private static XYSeries series1;
private NumberAxis domainAxis;
private double lowerBound;
private double upperBound;
public void adjustmentValueChanged(AdjustmentEvent e) {
// this method is called when the scrollbar changes
System.out.println(e.getValue());
JScrollBar scrollbar = (JScrollBar)e.getAdjustable();
int x = e.getValue();
this.domainAxis.setRange(lowerBound + x, upperBound + x);
System.out.println(x);
}
private JFreeChart chart;
public ScrollingLineChart() {
super("Scrolling Line Chart Demo");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
XYDataset dataset = createDataset();
this.chart = createChart(dataset);
this.domainAxis = (NumberAxis)this.chart.getXYPlot().getDomainAxis();
ChartPanel chartPanel = new ChartPanel(chart);
chartPanel.setPreferredSize(new java.awt.Dimension(500, 270));
this.add(chartPanel);
this.add(getScrollBar(), BorderLayout.SOUTH);
}
private JScrollBar getScrollBar() {
// JScrollBar(orientation, value, extent(size of the viewable are or visible amount), min, max)
// the scrollbar will return values in the range 0 to 100 or max - extent. Extent is the visual width of the slider
// value - the current value represented by the left top edge of the scrollbar
JScrollBar scrollBar = new JScrollBar(JScrollBar.HORIZONTAL,0,0,0,100);
// JScrollBar scrollBar = new JScrollBar(JScrollBar.HORIZONTAL);
scrollBar.addAdjustmentListener(this);
// System.out.println("Lower Bound: " + domainAxis.getRange().getLowerBound());
// System.out.println("Upper Bound: " + domainAxis.getRange().getUpperBound());
lowerBound = this.domainAxis.getLowerBound();
upperBound = this.domainAxis.getUpperBound();
// System.out.println(lowerBound);
// System.out.println(upperBound);
return scrollBar;
}
/**
* 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
null, // x axis label
null, // y axis label
dataset, // data
PlotOrientation.VERTICAL, false, // include legend
true, // tooltips
false // urls
);
// NOW DO SOME OPTIONAL CUSTOMISATION OF THE CHART...
chart.setBackgroundPaint(Color.BLACK);
// get a reference to the plot for further customisation...
XYPlot plot = (XYPlot) chart.getPlot();
plot.setBackgroundPaint(Color.BLACK);
plot.setAxisOffset(new RectangleInsets(5.0, 5.0, 5.0, 5.0));
plot.setDomainGridlinesVisible(false);
plot.setRangeGridlinesVisible(false);
XYLineAndShapeRenderer renderer = (XYLineAndShapeRenderer) plot
.getRenderer();
NumberAxis domainAxis = (NumberAxis) plot.getDomainAxis();
domainAxis.setAutoRange(true);
domainAxis.setAutoRangeIncludesZero(false);
// domainAxis.setRange(50,100);
// change the auto tick unit selection to integer units only...
NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis();
rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
// OPTIONAL CUSTOMISATION COMPLETED.
return chart;
}
/**
* Creates a sample dataset.
*
* @return a sample dataset.
*/
private static XYDataset createDataset() {
series1 = new XYSeries("First");
int randomX;
int randomY;
int min = -200;
int max = 200;
Random randomGenerator = new Random();
for (int i = 0; i < 1000; i++) {
randomX = (int) (Math.random() * (max - min + 1) ) + min;
randomY = randomGenerator.nextInt(50);
series1.add(randomX, randomY);
}
XYSeriesCollection dataset = new XYSeriesCollection();
dataset.addSeries(series1);
return dataset;
}
public static void main(String[] args) {
ScrollingLineChart scrollingChart = new ScrollingLineChart();
scrollingChart.pack();
scrollingChart.setVisible(true);
}
}