Understanding Visible Domain Range

A discussion forum for JFreeChart (a 2D chart library for the Java platform).
Locked
cobragtk
Posts: 11
Joined: Fri Jan 23, 2009 7:07 pm

Understanding Visible Domain Range

Post by cobragtk » Fri Feb 13, 2009 8:58 pm

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.

skunk
Posts: 1087
Joined: Thu Jun 02, 2005 10:14 pm
Location: Brisbane, Australia

Post by skunk » Fri Feb 13, 2009 9:37 pm

I suspect this will work a lot better when you map the indices of the data to the scrollbar instead of the actual data values.

cobragtk
Posts: 11
Joined: Fri Jan 23, 2009 7:07 pm

Post by cobragtk » Fri Feb 13, 2009 11:40 pm

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.

paradoxoff
Posts: 1634
Joined: Sat Feb 17, 2007 1:51 pm

Post by paradoxoff » Sat Feb 14, 2009 9:04 am

cobragtk wrote:If I then get the upper and lower bounds of the chart ...
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.
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).

mkivinie
Posts: 51
Joined: Wed Jul 06, 2005 8:35 am

Post by mkivinie » Mon Feb 16, 2009 5:25 pm

Visible range

Code: Select all

xyplot.getDomainAxis().getRange()
In your case 0...200

The whole datarange for all mapped datasets (useful if you have more than one dataset)

Code: Select all

xyplot.getDataRange( xyplot.getDomainAxis() )
In your case -200...200

cobragtk
Posts: 11
Joined: Fri Jan 23, 2009 7:07 pm

Post by cobragtk » Wed Feb 18, 2009 12:06 am

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.

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);
	}

}

Locked