Scaling and scrolling issues
Scaling and scrolling issues
Hello
As a JFreechart-newbie , i have some queries.
If you take for example the DynamicDataDemo.java file in demo folder of jfeechart installation , how could i possibly scale the points plotted along the y-axis.
Do i attach a javax.swing.Jslider vertically and use its events to scale the points . Will this work in good syncronization with the Dynamic Data demo?
Another doubt, in this demo, is it possible to add a HORIZONTAL_SCROLLBAR_AS_NEEDED to the panel so that over a larger period of time i could possibly drag my scrollbar to view previously logged results?
Any suggestions or sample codes would be very helpful.
And sorry for a long message, but the urgency of my need demands it!
Thanks in advance
Gaurav Kathotia
As a JFreechart-newbie , i have some queries.
If you take for example the DynamicDataDemo.java file in demo folder of jfeechart installation , how could i possibly scale the points plotted along the y-axis.
Do i attach a javax.swing.Jslider vertically and use its events to scale the points . Will this work in good syncronization with the Dynamic Data demo?
Another doubt, in this demo, is it possible to add a HORIZONTAL_SCROLLBAR_AS_NEEDED to the panel so that over a larger period of time i could possibly drag my scrollbar to view previously logged results?
Any suggestions or sample codes would be very helpful.
And sorry for a long message, but the urgency of my need demands it!
Thanks in advance
Gaurav Kathotia
Re: Scaling and scrolling issues
Gaurav Kathotia wrote:
> As a JFreechart-newbie , i have some queries.
> If you take for example the DynamicDataDemo.java file in demo
> folder of jfeechart installation , how could i possibly scale
> the points plotted along the y-axis.
In the demo, the y-axis range has a fixed range of 0 to 200. This is done with the following code:
axis = plot.getRangeAxis();
axis.setAxisRange(0.0, 200.0);
Comment out those lines and the range will adjust to fit the data (things jump around a bit until you have a reasonable amount of data).
> Do i attach a javax.swing.Jslider vertically and use its
> events to scale the points . Will this work in good
> syncronization with the Dynamic Data demo?
You could use a Swing component to control attributes on the chart...synchronising the positions could be tricky.
> Another doubt, in this demo, is it possible to add a
> HORIZONTAL_SCROLLBAR_AS_NEEDED to the panel so that over a
> larger period of time i could possibly drag my scrollbar to
> view previously logged results?
The chart is drawn on the JFreeChartPanel using the Java2D API. You can't really get a scroll bar just for the data section of the chart. I'm thinking about other ways to interactively scroll left and right through the data.
Regards,
DG.
> As a JFreechart-newbie , i have some queries.
> If you take for example the DynamicDataDemo.java file in demo
> folder of jfeechart installation , how could i possibly scale
> the points plotted along the y-axis.
In the demo, the y-axis range has a fixed range of 0 to 200. This is done with the following code:
axis = plot.getRangeAxis();
axis.setAxisRange(0.0, 200.0);
Comment out those lines and the range will adjust to fit the data (things jump around a bit until you have a reasonable amount of data).
> Do i attach a javax.swing.Jslider vertically and use its
> events to scale the points . Will this work in good
> syncronization with the Dynamic Data demo?
You could use a Swing component to control attributes on the chart...synchronising the positions could be tricky.
> Another doubt, in this demo, is it possible to add a
> HORIZONTAL_SCROLLBAR_AS_NEEDED to the panel so that over a
> larger period of time i could possibly drag my scrollbar to
> view previously logged results?
The chart is drawn on the JFreeChartPanel using the Java2D API. You can't really get a scroll bar just for the data section of the chart. I'm thinking about other ways to interactively scroll left and right through the data.
Regards,
DG.
Re: Scaling and scrolling issues
Thanks David
the Scaling issue seems to be resolved. But the main problem of
dynamic scrolling persists. Let me know if there are any alternatives
as soon as possible.
Regards
Gaurav Kathotia
the Scaling issue seems to be resolved. But the main problem of
dynamic scrolling persists. Let me know if there are any alternatives
as soon as possible.
Regards
Gaurav Kathotia
Dynamic Scrolling ?
Any updates on this feature...
This is about the only major feature thats missing imho from this API...
Or has it already been implemented ?
This is about the only major feature thats missing imho from this API...
Or has it already been implemented ?
At the url given below you can download the source code of a demo which shows how I have achieved pan and scroll functionality based on the JFreeChart lib version 0.9.8. You have a scollbar and several buttons which allow to toggle between pan and zoom mode. In pan mode you get a hand cursor and you can pan the (previously zoomed) chart as well as with the scollbar - like in Adobe Acrobat Reader for example; there is also a screenshot in this directory:
http://es.geocities.com/ickelockel/JFreeChart/
It is surely not a very good example as far as programming style or performance is concerned. My aim was to get this functionality quickly (not to wait until JFreeChart 1.0.0) and without changing the original JFreeChart code (I thought it could avoid to adapt the code for version 0.9.9, but this does not seem to be the case.) Anyway, it was only thought to be a temporary solution until similar functionalites will be provided by the standard JFreeChart library. Maybe someone else can use such a temporary solution (code/ideas).
http://es.geocities.com/ickelockel/JFreeChart/
It is surely not a very good example as far as programming style or performance is concerned. My aim was to get this functionality quickly (not to wait until JFreeChart 1.0.0) and without changing the original JFreeChart code (I thought it could avoid to adapt the code for version 0.9.9, but this does not seem to be the case.) Anyway, it was only thought to be a temporary solution until similar functionalites will be provided by the standard JFreeChart library. Maybe someone else can use such a temporary solution (code/ideas).
-
- Posts: 43
- Joined: Fri Mar 14, 2003 3:14 pm
- Location: Porto (Portugal)
- Contact:
sun.dc.pr.PRException: endPath: bad path
Hi Eduardo,
I don't get this Exception in the DemoApplication unter Java 1.4.0 and Windows NT, so I did nothing about a maximum zoom level.
But I remember, I had a similar Exception with some other Chart-Lib (Ilog). If you find the reason/a workaround please let me know.
Matthias
I don't get this Exception in the DemoApplication unter Java 1.4.0 and Windows NT, so I did nothing about a maximum zoom level.
But I remember, I had a similar Exception with some other Chart-Lib (Ilog). If you find the reason/a workaround please let me know.
Matthias
sun.dc.pr.PRException, setAntiAlias(false)
I see; it's the same with org.jfree.chart.demo.MouseZoomDemo and it seems to have to do with antialiasing:
http://developer.java.sun.com/developer ... 85298.html
http://developer.java.sun.com/developer ... 96289.html
WORKAROUND : Do not use antialiasing:
chart.setAntiAlias(false);
http://developer.java.sun.com/developer ... 85298.html
http://developer.java.sun.com/developer ... 96289.html
WORKAROUND : Do not use antialiasing:
chart.setAntiAlias(false);
-
- Posts: 43
- Joined: Fri Mar 14, 2003 3:14 pm
- Location: Porto (Portugal)
- Contact:
-
- Posts: 43
- Joined: Fri Mar 14, 2003 3:14 pm
- Location: Porto (Portugal)
- Contact:
Hi Matthias!
I adapted your code to work with JFreeChart 0.9.12.
Apparently is working correctly.
Regards,
Eduardo
I adapted your code to work with JFreeChart 0.9.12.
Apparently is working correctly.
Regards,
Eduardo
Code: Select all
/* ======================================
* Pan & Scroll & Zoom - Demo
* for JFreeChart library Version 0.9.8
* ======================================
* Author: Matthias Rose (Ablay & Fodi GmbH, Germany)
* E-mail: matthias.rose@ablay-fodi.de
* ======================================
* 01.07.2003: Initial version
* 15.09.2003: Adaptation to JFreeChart 0.9.12 (Eduardo Ramalho)
* ======================================
*/
package org.jfree.chart.demo;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import javax.swing.AbstractAction;
import javax.swing.AbstractButton;
import javax.swing.Action;
import javax.swing.BoundedRangeModel;
import javax.swing.ButtonGroup;
import javax.swing.DefaultBoundedRangeModel;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollBar;
import javax.swing.JToggleButton;
import javax.swing.JToolBar;
import javax.swing.UIManager;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.ChartRenderingInfo;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.TextTitle;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.event.ChartChangeEvent;
import org.jfree.chart.event.ChartChangeListener;
import org.jfree.chart.labels.StandardXYToolTipGenerator;
import org.jfree.chart.labels.XYToolTipGenerator;
import org.jfree.chart.plot.Plot;
import org.jfree.chart.plot.ValueAxisPlot;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.StandardXYItemRenderer;
import org.jfree.chart.renderer.XYItemRenderer;
import org.jfree.data.Range;
import org.jfree.data.XYSeries;
import org.jfree.data.XYSeriesCollection;
import org.jfree.ui.RefineryUtilities;
import com.sun.java.swing.plaf.windows.WindowsLookAndFeel;
public class PanScrollZoomDemo
extends JFrame
implements
ActionListener,
ChangeListener,
ChartChangeListener,
MouseListener,
MouseMotionListener {
private ChartPanel chartPanel;
private double scrollFactor = 1000;
private JScrollBar scrollBar;
private Point2D panStartPoint;
private double primYMinMax[] = new double[2];
private double secondYMinMax[] = new double[2];
// action commands
private static final String ACTION_CMD_PAN = "pan";
private static final String ACTION_CMD_ZOOM_BOX = "zoomBox";
private static final String ACTION_CMD_ZOOM_TO_FIT = "zoomFit";
private static final String ACTION_CMD_ZOOM_IN = "zoomIn";
private static final String ACTION_CMD_ZOOM_OUT = "zoomOut";
private static final double ZOOM_FACTOR = 0.8;
private JToolBar toolBar;
private AbstractButton zoomButton, panButton;
private AbstractButton zoomInButton, zoomOutButton, fitButton;
public PanScrollZoomDemo(String frameTitle) {
super(frameTitle);
getContentPane().setLayout(new BorderLayout());
this.getContentPane().add(
this.toolBar = createToolbar(),
BorderLayout.SOUTH);
JFreeChart chart = createChart();
scrollBar.setModel(new DefaultBoundedRangeModel());
recalcScrollBar(chart.getPlot());
this.chartPanel = new ChartPanel(chart) {
public void autoRangeBoth() {
System.out.println("Use 'Fit all' button");
}
};
chart.addChangeListener(this);
// enable zoom
actionPerformed(new ActionEvent(this, 0, ACTION_CMD_ZOOM_BOX));
// MouseListeners for pan function
chartPanel.addMouseListener(this);
chartPanel.addMouseMotionListener(this);
// remove popup menu to allow panning
// with right mouse pressed
chartPanel.setPopupMenu(null);
this.getContentPane().add(this.chartPanel);
}
private JFreeChart createChart() {
XYSeriesCollection primaryJFreeColl = new XYSeriesCollection();
XYSeries left1 = new XYSeries("Left 1");
left1.add(1, 2);
left1.add(2.8, 5.9);
left1.add(3, null);
left1.add(3.4, 2);
left1.add(5, -1);
left1.add(7, 1);
primaryJFreeColl.addSeries(left1);
XYSeriesCollection secondaryJFreeColl = new XYSeriesCollection();
XYSeries right1 = new XYSeries("Right 1");
right1.add(3.5, 2.2);
right1.add(1.2, 1.3);
right1.add(5.7, 4.1);
right1.add(7.5, 7.4);
secondaryJFreeColl.addSeries(right1);
NumberAxis xAxis = new NumberAxis("X");
xAxis.setAutoRangeIncludesZero(false);
xAxis.setAutoRangeStickyZero(false);
NumberAxis primaryYAxis = new NumberAxis("Y1");
primaryYAxis.setAutoRangeIncludesZero(false);
primaryYAxis.setAutoRangeStickyZero(false);
// create plot
XYToolTipGenerator toolTipGenerator = new StandardXYToolTipGenerator();
XYItemRenderer y1Renderer =
new StandardXYItemRenderer(StandardXYItemRenderer.LINES);
y1Renderer.setSeriesPaint(0, Color.BLUE);
y1Renderer.setToolTipGenerator(toolTipGenerator);
XYPlot xyPlot = new XYPlot(primaryJFreeColl, xAxis, primaryYAxis, y1Renderer);
// 2nd y-axis
NumberAxis secondaryYAxis = new NumberAxis("Y2");
secondaryYAxis.setAutoRangeIncludesZero(false);
secondaryYAxis.setAutoRangeStickyZero(false);
xyPlot.setSecondaryRangeAxis(0, secondaryYAxis);
xyPlot.setSecondaryDataset(0, secondaryJFreeColl);
xyPlot.mapSecondaryDatasetToRangeAxis(0, new Integer(0));
xyPlot.mapSecondaryDatasetToDomainAxis(0, new Integer(0));
XYItemRenderer y2Renderer =
new StandardXYItemRenderer(StandardXYItemRenderer.SHAPES_AND_LINES);
y2Renderer.setToolTipGenerator(toolTipGenerator);
xyPlot.setSecondaryRenderer(0, y2Renderer);
// set some fixed y-dataranges and remember them
// because default chartPanel.autoRangeBoth()
// would destroy them
ValueAxis axis = xyPlot.getRangeAxis();
axis.setLowerBound(primYMinMax[0] = -5);
axis.setUpperBound(primYMinMax[1] = 15);
axis = xyPlot.getSecondaryRangeAxis(0);
axis.setLowerBound(secondYMinMax[0] = -1);
axis.setUpperBound(secondYMinMax[1] = 10);
// Title + legend
String title = "To pan in zoom mode hold right mouse pressed";
JFreeChart ret = new JFreeChart(title, null, xyPlot, true);
TextTitle textTitle =
new TextTitle("(but you can only pan if the chart was zoomed before)");
ret.addSubtitle(textTitle);
return ret;
}
/**
* Creates the toolbar
*/
private JToolBar createToolbar() {
JToolBar toolbar = new JToolBar();
ButtonGroup groupedButtons = new ButtonGroup();
// ACTION_CMD_PAN
panButton = new JToggleButton();
prepareButton(panButton, ACTION_CMD_PAN, " P ", "Pan mode");
groupedButtons.add(panButton);
toolbar.add(panButton);
// ACTION_CMD_ZOOM_BOX
zoomButton = new JToggleButton();
prepareButton(zoomButton, ACTION_CMD_ZOOM_BOX, " Z ", "Zoom mode");
groupedButtons.add(zoomButton);
zoomButton.setSelected(true); // no other makes sense after startup
toolbar.add(zoomButton);
// end of toggle-button group for select/pan/zoom-box
toolbar.addSeparator();
// ACTION_CMD_ZOOM_IN
zoomInButton = new JButton();
prepareButton(zoomInButton, ACTION_CMD_ZOOM_IN, " + ", "Zoom in");
toolbar.add(zoomInButton);
// ACTION_CMD_ZOOM_OUT
zoomOutButton = new JButton();
prepareButton(zoomOutButton, ACTION_CMD_ZOOM_OUT, " - ", "Zoom out");
toolbar.add(zoomOutButton);
// ACTION_CMD_ZOOM_TO_FIT
fitButton = new JButton();
prepareButton(fitButton, ACTION_CMD_ZOOM_TO_FIT, " # ", "Fit all");
toolbar.add(fitButton);
toolbar.addSeparator();
scrollBar = new JScrollBar(JScrollBar.HORIZONTAL);
int ht = (int) zoomButton.getPreferredSize().getHeight();
scrollBar.setPreferredSize(new Dimension(0, ht));
scrollBar.setModel(new DefaultBoundedRangeModel());
toolbar.add(scrollBar);
zoomOutButton.setEnabled(false);
fitButton.setEnabled(false);
scrollBar.setEnabled(false);
toolbar.setFloatable(false);
return toolbar;
}
private void prepareButton(
AbstractButton button,
String actionKey,
String buttonLabelText,
String toolTipText) {
Action action = new AbstractAction(actionKey) {
public void actionPerformed(ActionEvent evt) {
}
};
button.setAction(action);
button.setActionCommand(actionKey);
button.setText(buttonLabelText);
button.setToolTipText(toolTipText);
button.addActionListener(this);
}
private void setPanMode(boolean val) {
chartPanel.setHorizontalZoom(!val);
// chartPanel.setHorizontalAxisTrace(! val);
chartPanel.setVerticalZoom(!val);
// chartPanel.setVerticalAxisTrace(! val);
if (val)
chartPanel.setCursor(
Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
else
chartPanel.setCursor(Cursor.getDefaultCursor());
}
/**
* if a button is pressed ...
*/
public void actionPerformed(ActionEvent evt) {
try {
String acmd = evt.getActionCommand();
if (acmd.equals(ACTION_CMD_ZOOM_BOX)) {
setPanMode(false);
} else if (acmd.equals(ACTION_CMD_PAN)) {
setPanMode(true);
} else if (acmd.equals(ACTION_CMD_ZOOM_IN)) {
ChartRenderingInfo info = chartPanel.getChartRenderingInfo();
Rectangle2D rect = info.getDataArea();
zoomBoth(rect.getCenterX(), rect.getCenterY(), ZOOM_FACTOR);
} else if (acmd.equals(ACTION_CMD_ZOOM_OUT)) {
ChartRenderingInfo info = chartPanel.getChartRenderingInfo();
Rectangle2D rect = info.getDataArea();
zoomBoth(rect.getCenterX(), rect.getCenterY(), 1 / ZOOM_FACTOR);
} else if (acmd.equals(ACTION_CMD_ZOOM_TO_FIT)) {
// X-axis (has no fixed borders)
chartPanel.autoRangeHorizontal();
// Y-Axes) (autoRangeVertical
// not useful because of fixed borders
Plot plot = this.chartPanel.getChart().getPlot();
if (plot instanceof ValueAxisPlot) {
XYPlot vvPlot = (XYPlot) plot;
ValueAxis axis = vvPlot.getRangeAxis();
if (axis != null) {
axis.setLowerBound(primYMinMax[0]);
axis.setUpperBound(primYMinMax[1]);
}
if (vvPlot instanceof XYPlot) {
XYPlot xyPlot = (XYPlot) plot;
axis = xyPlot.getSecondaryRangeAxis(0);
if (axis != null) {
axis.setLowerBound(secondYMinMax[0]);
axis.setUpperBound(secondYMinMax[1]);
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* if the scrollbar is changed ...
*/
public void stateChanged(ChangeEvent evt) {
try {
Object src = evt.getSource();
BoundedRangeModel scrollBarModel = this.scrollBar.getModel();
if (src == scrollBarModel) {
int val = scrollBarModel.getValue();
int ext = scrollBarModel.getExtent();
Plot plot = chartPanel.getChart().getPlot();
if (plot instanceof XYPlot) {
XYPlot hvp = (XYPlot) plot;
ValueAxis axis = hvp.getDomainAxis();
// avoid problems
chartPanel.getChart().removeChangeListener(this);
axis.setRange(
val / scrollFactor,
(val + ext) / scrollFactor);
// restore chart listener
chartPanel.getChart().addChangeListener(this);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* if the data ranges are changed ...
*/
public void chartChanged(ChartChangeEvent evt) {
try {
if (evt.getChart() == null)
return;
BoundedRangeModel scrollBarModel = this.scrollBar.getModel();
if (scrollBarModel == null)
return;
boolean chartIsZoomed = false;
Plot plot = evt.getChart().getPlot();
if (plot instanceof XYPlot) {
XYPlot hvp = (XYPlot) plot;
ValueAxis xAxis = hvp.getDomainAxis();
Range xAxisRange = xAxis.getRange();
// avoid recursion
scrollBarModel.removeChangeListener(this);
int low = (int) (xAxisRange.getLowerBound() * scrollFactor);
scrollBarModel.setValue(low);
int ext =
(int) (xAxisRange.getUpperBound() * scrollFactor - low);
scrollBarModel.setExtent(ext);
// restore
scrollBarModel.addChangeListener(this);
// check if zoomed horizontally
//Range hdr = hvp.getHorizontalDataRange(xAxis);
Range hdr = hvp.getDataRange(xAxis);
double len = hdr == null ? 0 : hdr.getLength();
chartIsZoomed |= xAxisRange.getLength() < len;
}
if (!chartIsZoomed && plot instanceof XYPlot) {
// check if zoomed vertically
XYPlot vvp = (XYPlot) plot;
ValueAxis yAxis = vvp.getRangeAxis();
if (yAxis != null) {
chartIsZoomed =
yAxis.getLowerBound() > primYMinMax[0]
|| yAxis.getUpperBound() < primYMinMax[1];
// right y-axis
if (!chartIsZoomed && plot instanceof XYPlot) {
XYPlot xyPlot = (XYPlot) vvp;
yAxis = xyPlot.getSecondaryRangeAxis(0);
if (yAxis != null) {
chartIsZoomed =
yAxis.getLowerBound() > secondYMinMax[0]
|| yAxis.getUpperBound()
< secondYMinMax[1];
}
}
}
}
// enable "zoom-out-buttons" if chart is zoomed
// otherwise disable them
panButton.setEnabled(chartIsZoomed);
zoomOutButton.setEnabled(chartIsZoomed);
fitButton.setEnabled(chartIsZoomed);
scrollBar.setEnabled(chartIsZoomed);
if (!chartIsZoomed) {
setPanMode(false);
zoomButton.setSelected(true);
}
} catch (Exception e) {
e.printStackTrace();
}
}
// Mouse[Motion]Listeners for pan
public void mousePressed(MouseEvent evt) {
try {
if (panButton.isSelected()
|| panButton.isEnabled()
&& evt.getButton() == MouseEvent.BUTTON3) {
Rectangle2D dataArea = chartPanel.getScaledDataArea();
Point2D point = evt.getPoint();
if (dataArea.contains(point)) {
setPanMode(true);
panStartPoint = point;
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void mouseReleased(MouseEvent arg0) {
try {
this.panStartPoint = null; // stop panning
if (!panButton.isSelected())
setPanMode(false);
} catch (Exception e) {
e.printStackTrace();
}
}
/*
* does the panning
*/
public void mouseDragged(MouseEvent evt) {
try {
if (this.panStartPoint != null) {
Rectangle2D scaledDataArea = chartPanel.getScaledDataArea();
this.panStartPoint =
RefineryUtilities.getPointInRectangle(
this.panStartPoint.getX(),
this.panStartPoint.getY(),
scaledDataArea);
Point2D panEndPoint =
RefineryUtilities.getPointInRectangle(
evt.getX(),
evt.getY(),
scaledDataArea);
// horizontal pan
Plot plot = chartPanel.getChart().getPlot();
if (plot instanceof XYPlot) {
XYPlot hvp = (XYPlot) plot;
ValueAxis xAxis = hvp.getDomainAxis();
if (xAxis != null) {
double translatedStartPoint =
xAxis.translateJava2DtoValue(
(float) panStartPoint.getX(),
scaledDataArea,
hvp.getDomainAxisEdge());
double translatedEndPoint =
xAxis.translateJava2DtoValue(
(float) panEndPoint.getX(),
scaledDataArea,
hvp.getDomainAxisEdge());
double dX = translatedStartPoint - translatedEndPoint;
double oldMin = xAxis.getLowerBound();
double newMin = oldMin + dX;
double oldMax = xAxis.getUpperBound();
double newMax = oldMax + dX;
// do not pan out of range
if (newMin
>= hvp.getDataRange(xAxis).getLowerBound()
&& newMax
<= hvp
.getDataRange(xAxis)
.getUpperBound()) {
xAxis.setLowerBound(newMin);
xAxis.setUpperBound(newMax);
}
}
}
// vertical pan (1. Y-Axis)
if (plot instanceof XYPlot) {
XYPlot vvp = (XYPlot) plot;
ValueAxis yAxis = vvp.getRangeAxis();
if (yAxis != null) {
double translatedStartPoint =
yAxis.translateJava2DtoValue(
(float) panStartPoint.getY(),
scaledDataArea,
vvp.getRangeAxisEdge());
double translatedEndPoint =
yAxis.translateJava2DtoValue(
(float) panEndPoint.getY(),
scaledDataArea,
vvp.getRangeAxisEdge());
double dY = translatedStartPoint - translatedEndPoint;
double oldMin = yAxis.getLowerBound();
double newMin = oldMin + dY;
double oldMax = yAxis.getUpperBound();
double newMax = oldMax + dY;
// do not pan out of range
if (newMin >= primYMinMax[0]
&& newMax <= primYMinMax[1]) {
yAxis.setLowerBound(newMin);
yAxis.setUpperBound(newMax);
}
}
}
// vertical pan (2. Y-Axis)
if (plot instanceof XYPlot) {
XYPlot xyPlot = (XYPlot) plot;
ValueAxis yAxis = xyPlot.getSecondaryRangeAxis(0);
if (yAxis != null) {
double translatedStartPoint =
yAxis.translateJava2DtoValue(
(float) panStartPoint.getY(),
scaledDataArea,
xyPlot.getSecondaryRangeAxisEdge(0));
double translatedEndPoint =
yAxis.translateJava2DtoValue(
(float) panEndPoint.getY(),
scaledDataArea,
xyPlot.getSecondaryRangeAxisEdge(0));
double dY = translatedStartPoint - translatedEndPoint;
double oldMin = yAxis.getLowerBound();
double newMin = oldMin + dY;
double oldMax = yAxis.getUpperBound();
double newMax = oldMax + dY;
if (newMin >= secondYMinMax[0]
&& newMax <= secondYMinMax[1]) {
yAxis.setLowerBound(newMin);
yAxis.setUpperBound(newMax);
}
}
}
// for the next time
this.panStartPoint = panEndPoint;
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void mouseClicked(MouseEvent evt) {
;
}
public void mouseMoved(MouseEvent evt) {
;
}
public void mouseEntered(MouseEvent evt) {
;
}
public void mouseExited(MouseEvent evt) {
;
}
public static void main(String[] args) {
try {
final String lookAndFeelClassName =
WindowsLookAndFeel.class.getName();
UIManager.setLookAndFeel(lookAndFeelClassName);
} catch (Exception ex) {
System.out.println(ex.getMessage());
}
PanScrollZoomDemo demo =
new PanScrollZoomDemo("Pan & Scroll & Zoom - Demo");
demo.pack();
demo.setVisible(true);
}
// private
private void recalcScrollBar(Plot plot) {
if (plot instanceof XYPlot) {
XYPlot hvp = (XYPlot) plot;
ValueAxis axis = hvp.getDomainAxis();
axis.setLowerMargin(0);
axis.setUpperMargin(0);
Range rng = axis.getRange();
BoundedRangeModel scrollBarModel = this.scrollBar.getModel();
int len = scrollBarModel.getMaximum() - scrollBarModel.getMinimum();
if (rng.getLength() > 0)
scrollFactor = len / rng.getLength();
double dblow = rng.getLowerBound();
int ilow = (int) (dblow * scrollFactor);
scrollBarModel.setMinimum(ilow);
int val = ilow;
scrollBarModel.setValue(val);
double dbup = rng.getUpperBound();
int iup = (int) (dbup * scrollFactor);
scrollBarModel.setMaximum(iup);
int ext = iup - ilow;
scrollBarModel.setExtent(ext);
scrollBarModel.addChangeListener(this);
}
}
/**
* Zooms in on an anchor point (measured in Java2D coordinates).
*
* @param x The x value.
* @param y The y value.
* @param zoomFactor The zoomFactor < 1 == zoom in; else out.
*/
private void zoomBoth(double x, double y, double zoomFactor) {
zoomHorizontal(x, zoomFactor);
zoomVertical(y, zoomFactor);
}
/**
* Decreases the range on the horizontal axis, centered about a Java2D
* x coordinate.
* <P>
* The range on the x axis is multiplied by zoomFactor
*
* @param x The x coordinate in Java2D space.
* @param zoomFactor The zoomFactor < 1 == zoom in; else out.
*/
private void zoomHorizontal(double x, double zoomFactor) {
JFreeChart chart = this.chartPanel.getChart();
ChartRenderingInfo info = chartPanel.getChartRenderingInfo();
if (chart.getPlot() instanceof XYPlot) {
XYPlot hvp = (XYPlot) chart.getPlot();
ValueAxis axis = hvp.getDomainAxis();
if (axis != null) {
double anchorValue =
axis.translateJava2DtoValue((float) x, info.getDataArea(), hvp.getDomainAxisEdge());
if (zoomFactor < 1.0) {
axis.resizeRange(zoomFactor, anchorValue);
} else if (zoomFactor > 1.0) {
Range range = hvp.getDataRange(axis);
adjustRange(axis, range, zoomFactor, anchorValue);
}
}
}
}
/**
* Decreases the range on the vertical axis, centered about a Java2D
* y coordinate.
* <P>
* The range on the y axis is multiplied by zoomFactor
*
* @param y The y coordinate in Java2D space.
* @param zoomFactor The zoomFactor < 1 == zoom in; else out.
*/
private void zoomVertical(double y, double zoomFactor) {
JFreeChart chart = this.chartPanel.getChart();
ChartRenderingInfo info = chartPanel.getChartRenderingInfo();
// 1. (left) Y-Axis
if (chart.getPlot() instanceof XYPlot) {
XYPlot vvp = (XYPlot) chart.getPlot();
ValueAxis primYAxis = vvp.getRangeAxis();
if (primYAxis != null) {
double anchorValue =
primYAxis.translateJava2DtoValue(
(float) y,
info.getDataArea(),
vvp.getRangeAxisEdge());
if (zoomFactor < 1.0) {
// zoom in
primYAxis.resizeRange(zoomFactor, anchorValue);
} else if (zoomFactor > 1.0) {
// zoom out
Range range = new Range(primYMinMax[0], primYMinMax[1]);
adjustRange(primYAxis, range, zoomFactor, anchorValue);
}
}
// 2. (right) Y-Axis
if (chart.getPlot() instanceof XYPlot) {
XYPlot xyp = (XYPlot) chart.getPlot();
ValueAxis secYAxis = xyp.getSecondaryRangeAxis(0);
if (secYAxis != null) {
double anchorValue =
secYAxis.translateJava2DtoValue(
(float) y,
info.getDataArea(),
xyp.getSecondaryRangeAxisEdge(0));
if (zoomFactor < 1.0) {
// zoom in
secYAxis.resizeRange(zoomFactor, anchorValue);
} else if (zoomFactor > 1.0) {
// zoom out
Range range =
new Range(secondYMinMax[0], secondYMinMax[1]);
adjustRange(secYAxis, range, zoomFactor, anchorValue);
}
}
}
}
}
/**
* used for zooming
*/
private void adjustRange(
ValueAxis axis,
Range range,
double zoomFactor,
double anchorValue) {
if (axis == null || range == null)
return;
double rangeMinVal =
range.getLowerBound() - range.getLength() * axis.getLowerMargin();
double rangeMaxVal =
range.getUpperBound() + range.getLength() * axis.getUpperMargin();
double halfLength = axis.getRange().getLength() * zoomFactor / 2;
double zoomedMinVal = anchorValue - halfLength;
double zoomedMaxVal = anchorValue + halfLength;
double adjMinVal = zoomedMinVal;
if (zoomedMinVal < rangeMinVal) {
adjMinVal = rangeMinVal;
zoomedMaxVal += rangeMinVal - zoomedMinVal;
}
double adjMaxVal = zoomedMaxVal;
if (zoomedMaxVal > rangeMaxVal) {
adjMaxVal = rangeMaxVal;
zoomedMinVal -= zoomedMaxVal - rangeMaxVal;
adjMinVal = Math.max(zoomedMinVal, rangeMinVal);
}
Range adjusted = new Range(adjMinVal, adjMaxVal);
axis.setRange(adjusted);
}
}
Hi Eduard0, Matthias,
I wanted to try your excample, but I get the error "The method getDataArea() is undefined for the type ChartRenderingInfo" with info.getDataArea()
Can you help me what to use instead? Perhaps the API changed. I use the 0.9.14.
Gerd
[quote="Eduardo Ramalho"]Hi Matthias!
I adapted your code to work with JFreeChart 0.9.12.
Apparently is working correctly.
Regards,
Eduardo
I wanted to try your excample, but I get the error "The method getDataArea() is undefined for the type ChartRenderingInfo" with info.getDataArea()
Can you help me what to use instead? Perhaps the API changed. I use the 0.9.14.
Gerd
[quote="Eduardo Ramalho"]Hi Matthias!
I adapted your code to work with JFreeChart 0.9.12.
Apparently is working correctly.
Regards,
Eduardo
The solution
I tried it with getChartArea() instead and it works fine.
Many thanks for help
Gerd
Many thanks for help
Gerd
-
- JFreeChart Project Leader
- Posts: 11734
- Joined: Fri Mar 14, 2003 10:29 am
- antibot: No, of course not.
- Contact:
I've adapted the above code to work with the latest code in CVS. I'll probably include the demo with the 0.9.17 release.
David Gilbert
JFreeChart Project Leader
Read my blog
Support JFree via the Github sponsorship program
JFreeChart Project Leader


Get Curve fit in graph while scrolling
Hello ,
I very interested by the new PanZomSrollDemo inspired by Matthias and
Eduardo.
Is there any way to make the displayed curves fit in Y direction while scrolling in X direction?
(meaning that the Min/Max values of the curve are automaticaly scalled in the window).
I think that this improvement would permit to avoid panning.
I am interested also in local zooming (meaning for example to move a zoom icon with the mouse a the place and the with a click get the aera zoomed.
Did anybody already worked on this idea ?
Thank you
I very interested by the new PanZomSrollDemo inspired by Matthias and
Eduardo.
Is there any way to make the displayed curves fit in Y direction while scrolling in X direction?
(meaning that the Min/Max values of the curve are automaticaly scalled in the window).
I think that this improvement would permit to avoid panning.
I am interested also in local zooming (meaning for example to move a zoom icon with the mouse a the place and the with a click get the aera zoomed.
Did anybody already worked on this idea ?
Thank you