TIP: using the zoom rectangle for your own purposes

A discussion forum for JFreeChart (a 2D chart library for the Java platform).
Locked
jpmaia
Posts: 53
Joined: Fri Feb 22, 2008 10:44 pm

TIP: using the zoom rectangle for your own purposes

Post by jpmaia » Mon Apr 07, 2008 11:33 pm

Hopefully, the following might be of interest to some of you, and save you some time figuring this out for yourself....

I've figured out how to get the "zoom rectangle" to draw without actually zooming the chart. By the way, I am using JFreeChart 1.0.9. For my application, I am implementing CTRL-[mouse-zoom-rectangle] for a custom non-zooming action. If anyone is interested, here are the basics....

If you override the "mousePressed" and "mouseReleased" methods from "ChartPanel", you can save off the begin point and end point of the rectangle, then you need to do the appropriate window-to-chart coordinate conversion math you can find in some of the demo programs.

After I gather this info, I then call the respective "super" methods. However, in the "mouseReleased" method, before calling "super.mouseReleased", in an =if= block entered only if the CTRL button has been pressed, I first call one of my own methods to do the custom processing for the selected points, then I call "setMouseZoomable(false);" to temporarily turn off zooming, then I call "super.mouseReleased" to complete the zoom-rectangle processing without any zooming (the rectangle is removed from the window), then I call "setMouseZoomable(true);" to turn zooming back on again.

This works very nicely - I get my data points, ChartPanel draws the rectangle for me, and the chart does not zoom.


I am currently figuring out how to get the individual data points using the rectangle the user has drawn.

jpmaia
Posts: 53
Joined: Fri Feb 22, 2008 10:44 pm

Post by jpmaia » Mon Apr 21, 2008 6:33 pm

Update:

I successfully finished this implementation.

There apparently is no easy way to get all the chart data points within a rectangle on the chart. I ended up getting all the ChartEntities, filtering for the XYItemEntities, then using the rectangle coordinates I had previously saved to check which items were within the rectangle (the "Rectangle2D.Double" class has method "outcode" which tells you whether a point is within the rectangle).

jpmaia
Posts: 53
Joined: Fri Feb 22, 2008 10:44 pm

Post by jpmaia » Mon May 19, 2008 11:30 pm

Since someone asked in another thread, I'll copy my response here as well as to a little more detail on determining which data points are within a selecting rectangle....


It is a bit more involved than just a few lines to do this.

Essentially, you do the following:
- get the chart rendering info from the panel.
- get the entity collection from the rendering info.
- loop through the entity collection and for the XYItemEntity-s you
compare their chart position with the saved rectangle for the
selection area. The 'outcode' method for the rectangle area
should be used to see if the x/y location of the item entities
are within the rectangle (a value of 0 indicates it is).
- you now have the list of items within the selection area.
- you will have to map these item entities to any data associated
with your chart points since these entities provide strictly chart
plotting info. You can get the series index and item index from
these entities. I used these indexes to reference data I saved
external to JFreeChart.

suhagun
Posts: 6
Joined: Thu Jul 10, 2008 2:29 am

Post by suhagun » Thu Jul 10, 2008 3:30 am

Can you share the full code for the class where you are getting the zoom rectangle points? I need to do the same. Since I am extending JFrame for the main class I am confused about how to override the CharPanel mouse event methods.

thanks

krheinwald
Posts: 15
Joined: Thu Mar 27, 2003 10:06 am

Re: TIP: using the zoom rectangle for your own purposes

Post by krheinwald » Thu Jul 10, 2008 4:57 pm

jpmaia wrote:This works very nicely - I get my data points, ChartPanel draws the rectangle for me, and the chart does not zoom.
Would you mind posting a short example?

Klaus

khanhlv
Posts: 21
Joined: Thu May 22, 2008 10:27 am

Post by khanhlv » Wed Aug 13, 2008 9:01 am

I am also implementing this function too.
Can you share a short example!

Thank very much!

khanhlv
Posts: 21
Joined: Thu May 22, 2008 10:27 am

Post by khanhlv » Thu Aug 14, 2008 9:15 am

I am doing the same. I have implemented the function to get the rectangle but the problem is how to get the data in that rectangle?.
The best way is that I want to get the domain and range value at the upper point and lower point of rectangle.
Do you have any solution? I do not find any function to get the domain and range value based on the x,y-coordinate.

khanhlv
Posts: 21
Joined: Thu May 22, 2008 10:27 am

Post by khanhlv » Fri Aug 15, 2008 3:46 am

I have implemented this function. but the way i get the data in rectangle is different. I get the first point and the second point of rectangle. After that i transform these value to the x,y axis of graph. So based on these 2 points value and the dataset, I can get all the point in this rectangle.

Here is my code:

package common;



public class MyChartPanel extends org.jfree.chart.ChartPanel implements MouseListener {

private boolean isPressingCtrl = false;
private JFreeChart chart = null;

/**
* constructor
* @param chart
*/
public MyChartPanel(JFreeChart chart)
{
super(chart);
this.chart = chart;
addKeyEventListener();
}

/**
* add key listener for this panel
*/
private void addKeyEventListener()
{

// add key listener for press control key event
InputMap inputMap = this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);

KeyStroke controlPressedStroke = KeyStroke.getKeyStroke("ctrl CONTROL");
Action controlPressedAction = new AbstractAction()
{
public void actionPerformed(ActionEvent actionEvent)
{
if (!isPressingCtrl)
{
isPressingCtrl = true;
}
}
};

inputMap.put(controlPressedStroke, "ctrl CONTROL");
this.getActionMap().put("ctrl CONTROL", controlPressedAction);

// add key listener for release control key event
KeyStroke controlReleasedStroke = KeyStroke.getKeyStroke("released CONTROL");
Action controlReleasedAction = new AbstractAction()
{
public void actionPerformed(ActionEvent actionEvent)
{
if (isPressingCtrl)
{
isPressingCtrl = false;
}
}
};
inputMap.put(controlReleasedStroke, "released CONTROL");
this.getActionMap().put("released CONTROL", controlReleasedAction);
}


/**
* override the mouse pressed method
* Handles a 'mouse pressed' event.
* @param e information about the event.
*/
public void mousePressed(MouseEvent e)
{
if (isPressingCtrl)
{
System.out.println("mouse pressed");
setMouseZoomable(false,true);
super.mousePressed(e);
getPointInChart(e);
setMouseZoomable(true,false);

}
else{
super.mousePressed(e);
}
}

/**
* override the mouse released method
* Handles a 'mouse released' event.
* @param e information about the event.
*/
public void mouseReleased(MouseEvent e)
{
if (isPressingCtrl)
{
System.out.println("mouse released");
setMouseZoomable(false,true);
super.mouseReleased(e);
getPointInChart(e);
setMouseZoomable(true,false);

}
else
{
super.mouseReleased(e);
}
}



/**
* Receives chart x,y axis.
*
* @param e mouse event.
*/
public void getPointInChart(MouseEvent e)
{
Insets insets = getInsets();
int mouseX = (int) ((e.getX() - insets.left) / this.getScaleX());
int mouseY = (int) ((e.getY() - insets.top) / this.getScaleY());
System.out.println("x = " + mouseX + ", y = " + mouseY);

Point2D p = this.translateScreenToJava2D(new Point(mouseX, mouseY));
XYPlot plot = (XYPlot) chart.getPlot();
ChartRenderingInfo info = this.getChartRenderingInfo();
Rectangle2D dataArea = info.getPlotInfo().getDataArea();

ValueAxis domainAxis = plot.getDomainAxis();
RectangleEdge domainAxisEdge = plot.getDomainAxisEdge();
ValueAxis rangeAxis = plot.getRangeAxis();
RectangleEdge rangeAxisEdge = plot.getRangeAxisEdge();

double chartX = domainAxis.java2DToValue(p.getX(), dataArea, domainAxisEdge);
double chartY = rangeAxis.java2DToValue(p.getY(), dataArea, rangeAxisEdge);
System.out.println("Chart: x = " + chartX + ", y = " + chartY);
}



}

jpmaia
Posts: 53
Joined: Fri Feb 22, 2008 10:44 pm

Post by jpmaia » Mon Aug 18, 2008 11:02 pm

I've been away for awhile so I haven't seen these more recent posts....

I develop code in an environment that does not have access to the internet, so it is problematic for me to add code examples in this forum. Given the amount of code involved for this solution, it would be rather time consuming to type this in.

The summary I provided of the basic things that need to be done, while not as helpful as actual code, does provide the necessary info to implement this solution.

The code example given above provides the initial part of determining the rectangle. The rest of the solution is to compare all of your data points with this rectangle to see which points are within it.

jgloving
Posts: 6
Joined: Wed Aug 13, 2008 9:36 pm

Post by jgloving » Tue Aug 19, 2008 9:24 pm

Is there anyone who has the example codes to share? the above codes are not runnable. Thanks!

khanhlv
Posts: 21
Joined: Thu May 22, 2008 10:27 am

Post by khanhlv » Wed Aug 20, 2008 8:34 am

The above code can not run immediately.
The code only implement the rectangle detection function. If you want to run you create chart normaly and put the above code in you project, after that in your code :

change:

ChartPanel chartPanel = new ChartPanel(chart);
--->
Chartpanel chartPanel = new MyChartPanel(chart);

Locked