Setting Range for X,Y Axis-JfreeChart - java

Any suggestions over how to set Range for X-Axis and Y-Axis.
My "X-Axis" Range is from "0.00 to 1.00" with difference of "0.05". I mean 0.00 0.05 0.10 0.15.....0.90 0.95 1.00
My "Y-Axis" Range is from "0.0 to 1.0" with difference of "0.1". I mean 0.0 0.1 0.2 0.3 0.4.........0.9 1.0
I tried doing this Way, but it's not reflecting on the Graph; I don't know how to apply it to ChartFactory.createScatterPlot().
final NumberAxis domainAxis = new NumberAxis("X-Axis");
domainAxis.setRange(0.00,1.00);
domainAxis.setTickUnit(new NumberTickUnit(0.1));
final NumberAxis rangeAxis = new NumberAxis("Y-Axis");
rangeAxis.setRange(0.0,1.0);
rangeAxis.setTickUnit(new NumberTickUnit(0.05));
public JPanel createDemoPanel() {
XYDataset dataset1 = samplexydataset2();
JFreeChart jfreechart = ChartFactory.createScatterPlot("Scatter Plot Demo",
"X", "Y",dataset1, PlotOrientation.VERTICAL, true, true, false);
}
Any help regarding this would be great.

I'm guessing your new NumberAxis instances aren't being used by the plot; it may be easier to use the existing ones from the factory.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.util.*;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import org.jfree.chart.*;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.axis.NumberTickUnit;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYItemRenderer;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
/**
* #see http://stackoverflow.com/questions/7231824
* #see http://stackoverflow.com/questions/7205742
* #see http://stackoverflow.com/questions/7208657
* #see http://stackoverflow.com/questions/7071057
*/
public class ScatterAdd extends JFrame {
private static final int N = 8;
private static final String title = "Scatter Add Demo";
private static final Random rand = new Random();
private XYSeries added = new XYSeries("Added");
public ScatterAdd(String s) {
super(s);
final ChartPanel chartPanel = createDemoPanel();
this.add(chartPanel, BorderLayout.CENTER);
JPanel control = new JPanel();
control.add(new JButton(new AbstractAction("Add") {
#Override
public void actionPerformed(ActionEvent e) {
for (int i = 0; i < N; i++) {
added.add(rand.nextDouble(), rand.nextDouble());
}
}
}));
this.add(control, BorderLayout.SOUTH);
}
private ChartPanel createDemoPanel() {
JFreeChart jfreechart = ChartFactory.createScatterPlot(
title, "X", "Y", createSampleData(),
PlotOrientation.VERTICAL, true, true, false);
XYPlot xyPlot = (XYPlot) jfreechart.getPlot();
xyPlot.setDomainCrosshairVisible(true);
xyPlot.setRangeCrosshairVisible(true);
XYItemRenderer renderer = xyPlot.getRenderer();
renderer.setSeriesPaint(0, Color.blue);
NumberAxis domain = (NumberAxis) xyPlot.getDomainAxis();
domain.setRange(0.00, 1.00);
domain.setTickUnit(new NumberTickUnit(0.1));
domain.setVerticalTickLabels(true);
NumberAxis range = (NumberAxis) xyPlot.getRangeAxis();
range.setRange(0.0, 1.0);
range.setTickUnit(new NumberTickUnit(0.1));
return new ChartPanel(jfreechart);
}
private XYDataset createSampleData() {
XYSeriesCollection xySeriesCollection = new XYSeriesCollection();
XYSeries series = new XYSeries("Random");
for (int i = 0; i < N * N; i++) {
double x = rand.nextDouble();
double y = rand.nextDouble();
series.add(x, y);
}
xySeriesCollection.addSeries(series);
xySeriesCollection.addSeries(added);
return xySeriesCollection;
}
public static void main(String args[]) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
ScatterAdd demo = new ScatterAdd(title);
demo.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
demo.pack();
demo.setLocationRelativeTo(null);
demo.setVisible(true);
}
});
}
}

Unless the code that you pasted is incomplete, it looks like your problem is that you didn't associate the NumberAxis objects that you created with your plot.
Instead of creating new NumberAxis objects manually, try getting the default ValueAxis objects that are associated with your plot, then modifying their properties:
XYPlot xyPlot = jfreechart.getXYPlot();
ValueAxis domainAxis = xyPlot.getDomainAxis();
ValueAxis rangeAxis = xyPlot.getRangeAxis();
domainAxis.setRange(0.0, 1.0);
domainAxis.setTickUnit(new NumberTickUnit(0.1));
rangeAxis.setRange(0.0, 1.0);
rangeAxis.setTickUnit(new NumberTickUnit(0.05));

Related

JFreeChart is plotting data but not drawing linear regression

I have used JFreeChart to represent my array of x and y. These arrays get plotted just fine, however theregression line is broken and never gets drawn. All the functions work such as plotting values except drawinputpoint and drawregressionline function. Somehow these two never work. I don't mind drawwinginputpoint a lot, but I like to be able to drawregressionline. My array has correct data, so not sure what is the issue. I am importing my arrays data into dataset in createDateSetFromFile function. My Home_JFrame has targetx and targety array. These have arraylist and has Double data type.
package gradleproject2;
import java.awt.Color;
import java.io.File;
import java.io.IOException;
import java.util.Scanner;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYItemRenderer;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.chart.ui.ApplicationFrame;
import org.jfree.data.function.LineFunction2D;
import org.jfree.data.general.DatasetUtils;
import org.jfree.data.statistics.Regression;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
import gradleproject2.Home_JFrame;
import org.jfree.ui.RefineryUtilities;
public class PriceEstimator extends ApplicationFrame{
private static final long serialVersionUID = 1L;
XYDataset inputData;
JFreeChart chart;
public static void main(String[] args) throws IOException {
PriceEstimator demo = new PriceEstimator();
demo.pack();
RefineryUtilities.centerFrameOnScreen(demo);
demo.setVisible(true);
demo.drawRegressionLine();
if (args.length >= 1 && args[0] != null) {
// Estimate the linear function given the input data
double regressionParameters[] = Regression.getOLSRegression(
demo.inputData, 0);
double x = Double.parseDouble(args[0]);
// Prepare a line function using the found parameters
LineFunction2D linefunction2d = new LineFunction2D(
regressionParameters[0], regressionParameters[1]);
// This is the estimated price
double y = linefunction2d.getValue(x);
demo.drawInputPoint(x, y);
}
}
public PriceEstimator() throws IOException {
super("Linear Regression");
// Read sample data from prices.txt file
inputData = createDatasetFromFile();
// Create the chart using the sample data
chart = createChart(inputData);
ChartPanel chartPanel = new ChartPanel(chart);
chartPanel.setPreferredSize(new java.awt.Dimension(500, 270));
setContentPane(chartPanel);
}
public XYDataset createDatasetFromFile() throws IOException {
ClassLoader classLoader = getClass().getClassLoader();
XYSeriesCollection dataset = new XYSeriesCollection();
XYSeries series = new XYSeries("Stock Item");
// Read the price and the date
for (int row = 0; row < Home_JFrame.targetx.size(); row++) {
series.add(Home_JFrame.targetx.get(row), Home_JFrame.targety.get(row));
}
dataset.addSeries(series);
Home_JFrame.targetx.clear();
Home_JFrame.targety.clear();
return dataset;
}
private JFreeChart createChart(XYDataset inputData) throws IOException {
// Create the chart using the data read from the prices.txt file
JFreeChart chart = ChartFactory.createScatterPlot(
"Stock Price", "Stock Date", "Stock Opening Price", inputData,
PlotOrientation.VERTICAL, true, true, false);
XYPlot plot = chart.getXYPlot();
plot.getRenderer().setSeriesPaint(0, Color.blue);
return chart;
}
private void drawRegressionLine() {
// Get the parameters 'a' and 'b' for an equation y = a + b * x,
// fitted to the inputData using ordinary least squares regression.
// a - regressionParameters[0], b - regressionParameters[1]
double regressionParameters[] = Regression.getOLSRegression(inputData,
0);
// Prepare a line function using the found parameters
LineFunction2D linefunction2d = new LineFunction2D(
regressionParameters[0], regressionParameters[1]);
// Creates a dataset by taking sample values from the line function
XYDataset dataset = DatasetUtils.sampleFunction2D(linefunction2d,
0D, 300, 100, "Fitted Regression Line");
// Draw the line dataset
XYPlot xyplot = chart.getXYPlot();
xyplot.setDataset(1, dataset);
XYLineAndShapeRenderer xylineandshaperenderer = new XYLineAndShapeRenderer(
true, false);
xylineandshaperenderer.setSeriesPaint(0, Color.YELLOW);
xyplot.setRenderer(1, xylineandshaperenderer);
}
private void drawInputPoint(double x, double y) {
// Create a new dataset with only one row
XYSeriesCollection dataset = new XYSeriesCollection();
String title = "Stock Date Distance: " + x + ", Stock Opening Price: " + y;
XYSeries series = new XYSeries(title);
series.add(x, y);
dataset.addSeries(series);
XYPlot plot = (XYPlot) chart.getPlot();
plot.setDataset(2, dataset);
XYItemRenderer renderer = new XYLineAndShapeRenderer(false, true);
plot.setRenderer(2, renderer);
}
}
It looks like you want a trend line though a scatter plot, but you may be creating unnecessary renderers in addition to the one instantiated by your chosen ChartFactory. To study the problem in isolation, modify this complete example to create a scatter plot and change the existing renderer to condition the trend line's display as desired.
JFreeChart chart = ChartFactory.createScatterPlot(…);
XYPlot plot = chart.getXYPlot();
XYLineAndShapeRenderer r = (XYLineAndShapeRenderer) plot.getRenderer();
r.setSeriesLinesVisible(1, Boolean.TRUE);
r.setSeriesShapesVisible(1, Boolean.FALSE);
Code:
import java.awt.Dimension;
import java.awt.EventQueue;
import java.util.Random;
import javax.swing.JFrame;
import org.jfree.chart.*;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.data.statistics.Regression;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
/**
* #see https://stackoverflow.com/a/37716411/230513
* #see http://stackoverflow.com/a/37716411/230513
*/
public class RegressionTest {
private static final int N = 16;
private static final Random R = new Random();
private static XYDataset createDataset() {
XYSeries series = new XYSeries("Data");
for (int i = 0; i < N; i++) {
series.add(i, R.nextGaussian() + i);
}
XYSeriesCollection xyData = new XYSeriesCollection(series);
double[] coefficients = Regression.getOLSRegression(xyData, 0);
double b = coefficients[0]; // intercept
double m = coefficients[1]; // slope
XYSeries trend = new XYSeries("Trend");
double x = series.getDataItem(0).getXValue();
trend.add(x, m * x + b);
x = series.getDataItem(series.getItemCount() - 1).getXValue();
trend.add(x, m * x + b);
xyData.addSeries(trend);
return xyData;
}
private static JFreeChart createChart(final XYDataset dataset) {
JFreeChart chart = ChartFactory.createScatterPlot("Test", "X", "Y",
dataset, PlotOrientation.VERTICAL, true, false, false);
XYPlot plot = chart.getXYPlot();
XYLineAndShapeRenderer r = (XYLineAndShapeRenderer) plot.getRenderer();
r.setSeriesLinesVisible(1, Boolean.TRUE);
r.setSeriesShapesVisible(1, Boolean.FALSE);
return chart;
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
XYDataset dataset = createDataset();
JFreeChart chart = createChart(dataset);
ChartPanel chartPanel = new ChartPanel(chart) {
#Override
public Dimension getPreferredSize() {
return new Dimension(640, 480);
}
};
f.add(chartPanel);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
});
}
}

JFreeChart AutoRange Doesn't Work on Multiple Series On The Same Plot

In this code I created 2 TimeSeries and added them to the same plot but the axis.setAutoRange(true) works only for the second series.
Is there a way to make the AutoRange work on both of the TimeSeries?
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.plot.XYPlot;
import org.jfree.data.time.Millisecond;
import org.jfree.data.time.TimeSeries;
import org.jfree.data.time.TimeSeriesCollection;
import org.jfree.ui.ApplicationFrame;
import org.jfree.ui.RefineryUtilities;
import javax.swing.*;
import java.awt.*;
public class Graph extends ApplicationFrame {
private TimeSeries seriesA;
private TimeSeries seriesB;
public Graph(final String windowTitle, int width, int height, String xTitle, String yTitle, String headerTitle, String graphTitle) {
super(windowTitle);
final TimeSeriesCollection dataset = new TimeSeriesCollection();
this.seriesA = new TimeSeries(graphTitle);
this.seriesB = new TimeSeries(graphTitle);
dataset.addSeries(this.seriesA);
dataset.addSeries(this.seriesB);
final JFreeChart chart = ChartFactory.createTimeSeriesChart(
headerTitle,//set title
xTitle,//set x title
yTitle,//set y title
dataset,
false,
false,
false
);
final XYPlot plot = chart.getXYPlot();
ValueAxis axis = plot.getDomainAxis();
axis.setFixedAutoRange(60000.0);
axis = plot.getRangeAxis();
axis.setAutoRange(true);
final ChartPanel chartPanel = new ChartPanel(chart);
final JPanel content = new JPanel(new BorderLayout());
content.add(chartPanel);
chartPanel.setPreferredSize(new java.awt.Dimension(width, height));
setContentPane(content);
}
public void addPointA(double y) {
this.seriesA.add(new Millisecond(), y);
}
public void addPointB(double y) {
this.seriesB.add(new Millisecond(), y);
}
public static void main(final String[] args) throws InterruptedException {
final Graph demo = new Graph("Demo",500,500,"Time","Value",
"Header1","graph1");//window title
demo.pack();//doesnt matter
RefineryUtilities.positionFrameOnScreen(demo,0.2,0.7);//manually choose window position %
demo.setVisible(true);//show window
double lastValue=80;//randomize input
while (true){
demo.addPointA(lastValue);
demo.addPointB(lastValue-100);
//randomize input
lastValue*=Math.random()*0.2-0.1+1.001;
lastValue+=Math.random()*2-1;
//limit input rate
Thread.sleep(100);
}
}
}
In this picture the axis.setAutoRange(true) works only for the red Graph (seriesB)
Several problems merit attention:
The name of each TimeSeries comprising a TimeSeriesCollection serves as a Comparable index; the names should be unique for reliable auto-ranging; enable the chart factory's legend to see the effect.
As shown in org.jfree.chart.demo.TimeSeriesChartDemo1, included in the distribution, auto-range typically requires no special settings.
Construct and manipulate Swing GUI objects only on the event dispatch thread.
Don't sleep() on the event dispatch thread; use javax.swing.Timer to pace updates.
Don't extend the top-level container needlessly.
Don't nest containers needlessly.
import java.awt.EventQueue;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.data.time.Millisecond;
import org.jfree.data.time.TimeSeries;
import org.jfree.data.time.TimeSeriesCollection;
import org.jfree.ui.ApplicationFrame;
import org.jfree.ui.RefineryUtilities;
import javax.swing.*;
import java.awt.event.*;
public class Graph extends ApplicationFrame {
private final TimeSeries seriesA = new TimeSeries("A");
private final TimeSeries seriesB = new TimeSeries("B");
public Graph(final String windowTitle, int width, int height,
String xTitle, String yTitle, String headerTitle, String graphTitle) {
super(windowTitle);
final TimeSeriesCollection dataset = new TimeSeriesCollection();
dataset.addSeries(this.seriesA);
dataset.addSeries(this.seriesB);
final JFreeChart chart = ChartFactory.createTimeSeriesChart(
headerTitle, xTitle, yTitle, dataset, true, true, false
);
ChartPanel chartPanel = new ChartPanel(chart);
chartPanel.setPreferredSize(new java.awt.Dimension(width, height));
add(chartPanel);
}
public void addPointA(double y) {
this.seriesA.add(new Millisecond(), y);
}
public void addPointB(double y) {
this.seriesB.add(new Millisecond(), y);
}
public static void main(final String[] args) {
EventQueue.invokeLater(() -> {
Graph demo = new Graph("Demo", 640, 480,
"Time", "Value", "Header", "Graph");
demo.pack();//matters a great deal
RefineryUtilities.centerFrameOnScreen(demo);
demo.setVisible(true);
new Timer(100, (new ActionListener() {
double lastValue = 80;
#Override
public void actionPerformed(ActionEvent e) {
demo.addPointA(lastValue);
demo.addPointB(lastValue - 100);
lastValue *= Math.random() * 0.2 - 0.1 + 1.001;
lastValue += Math.random() * 2 - 1;
}
})).start();
});
}
}

JFreeChart simple plot (parabola)

I wrote a simple parabola plot using JFreeChart.
package parabolademo;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartMouseEvent;
import org.jfree.chart.ChartMouseListener;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.data.function.Function2D;
import org.jfree.data.function.PolynomialFunction2D;
import org.jfree.data.general.DatasetUtilities;
import org.jfree.data.xy.XYDataset;
import org.jfree.ui.ApplicationFrame;
import org.jfree.ui.RefineryUtilities;
public class ParabolaDemo extends ApplicationFrame {
/*
* #param title the frame title.
*/
public ParabolaDemo(final String title) {
super(title);
double[] a = {0.0, 0.0, 3.0};
Function2D p = new PolynomialFunction2D(a);
XYDataset dataset = DatasetUtilities.sampleFunction2D(p, -20.0, 20.0, 100, "Function");
final JFreeChart chart = ChartFactory.createXYLineChart(
"Parabola",
"X",
"Y",
dataset,
PlotOrientation.VERTICAL,
true,
true,
false
);
final ChartPanel chartPanel = new ChartPanel(chart);
chartPanel.addChartMouseListener(new ChartMouseListener() {
#Override
public void chartMouseClicked(ChartMouseEvent cme) {
Point2D po = chartPanel.translateScreenToJava2D(cme.getTrigger().getPoint());
Rectangle2D plotArea = chartPanel.getScreenDataArea();
XYPlot plot = (XYPlot) chart.getPlot(); // your plot
double chartX = plot.getDomainAxis().java2DToValue(po.getX(), plotArea, plot.getDomainAxisEdge());
double chartY = plot.getRangeAxis().java2DToValue(po.getY(), plotArea, plot.getRangeAxisEdge());
System.out.println("Clicked!");
System.out.println("X:" + chartX + ", Y:" + chartY);
}
#Override
public void chartMouseMoved(ChartMouseEvent cme) {
}
});
chartPanel.setPreferredSize(new java.awt.Dimension(500, 270));
setContentPane(chartPanel);
}
public static void main(final String[] args) {
final ParabolaDemo demo = new ParabolaDemo("Parabola Plot Demo");
demo.pack();
RefineryUtilities.centerFrameOnScreen(demo);
demo.setVisible(true);
}
}
How to get coordinates of FUNCTION PLOT point (my chartMouseListener get coordinates of any point in window)? how to receive point coordinates after the user moved mouse and released the mouse button?
I want that when clicking a mouse, the point of the plot followed a mouse, thus the plot will be rebuilt (for this purpose it is necessary to calculate again coefficients, knowing this coordinate and having taken any 2 other coordinates). How it can be done? How rebuilt plot with new coefficients?
Given a ChartMouseEvent named cmd, ignore entities of any type other than XYItemEntity. Once you know the entity, don't interpolate—just query the dataset.
ChartEntity ce = cme.getEntity();
if (ce instanceof XYItemEntity) {
XYItemEntity e = (XYItemEntity) ce;
XYDataset d = e.getDataset();
int s = e.getSeriesIndex();
int i = e.getItem();
System.out.println("X:" + d.getX(s, i) + ", Y:" + d.getY(s, i));
}
Also consider invoking setBaseShapesVisible(true) on the plot's renderer.

Dynamically repaint ScatterPlot in jfreechart

I have a scatterplot which plots positions of agents. These positions change. I was wondering how can I repaint/redraw the scatterplot with the new positions
my drawing method. I need to redraw in the updatePositions function. Is there any way to implement any listener for ScatterPlot?
private ChartPanel createPanel() {
JFreeChart jfreechart = ChartFactory.createScatterPlot(
title, "", "", initPositions(),PlotOrientation.VERTICAL, true, true, false);
XYPlot xyPlot = (XYPlot) jfreechart.getPlot();
xyPlot.setDomainCrosshairVisible(true);
xyPlot.setRangeCrosshairVisible(true);
XYItemRenderer renderer = xyPlot.getRenderer();
renderer.setSeriesPaint(0, Color.blue);
adjustAxis((NumberAxis) xyPlot.getDomainAxis(), true);
adjustAxis((NumberAxis) xyPlot.getRangeAxis(), false);
xyPlot.setBackgroundPaint(Color.white);
return new ChartPanel(jfreechart);
}
private void adjustAxis(NumberAxis axis, boolean vertical) {
axis.setRange(-1, lattice+1);
axis.setTickUnit(new NumberTickUnit(1));
axis.setVerticalTickLabels(vertical);
}
private XYDataset initPositions() {
XYSeriesCollection xySeriesCollection = new XYSeriesCollection();
for (int i = 0; i < populationSize; i++) {
if(population.get(i).status==1){
healthy.add(population.get(i).position[0], population.get(i).position[1]);
}else if(population.get(i).status==2){
infected.add(population.get(i).position[0], population.get(i).position[1]);
}else if(population.get(i).status==3){
recovered.add(population.get(i).position[0], population.get(i).position[1]);
}
}
xySeriesCollection.addSeries(healthy);
xySeriesCollection.addSeries(infected);
xySeriesCollection.addSeries(recovered);
return xySeriesCollection;
}
public void clear(){
healthy.clear();
infected.clear();
recovered.clear();
}
public void updatePositions(ArrayList<Person> pop ){
population = pop;
for (int i = 0; i < populationSize; i++) {
if(population.get(i).status==1){
healthy.addOrUpdate(population.get(i).position[0], population.get(i).position[1]);
}else if(population.get(i).status==2){
infected.addOrUpdate(population.get(i).position[0], population.get(i).position[1]);
}else if(population.get(i).status==3){
recovered.addOrUpdate(population.get(i).position[0], population.get(i).position[1]);
}
}
}
this is the method in the main class. The update of the positions is done at the "move" function
public static void main(String [] args){
createPopulation(populationSize);
initInfection(infectRatio);
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
DrawArea demo = new DrawArea("Demo", lattice, populationSize,population);
demo.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
demo.pack();
demo.setLocationRelativeTo(null);
demo.setVisible(true);
for(int i =0;i<1000;i++){
for(int j=0; j<populationSize; j++){
population.get(j).move(0.8);
}
demo.clear();
demo.updatePositions(population);
}
}
});
}
As shown below, the chart (view) listens to its dataset (model) and updates itself accordingly. When the Move button is pressed, each XYDataItem in the series in modified in update() to reflect its new position.
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.util.*;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import org.jfree.chart.*;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.axis.NumberTickUnit;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYItemRenderer;
import org.jfree.data.xy.XYDataItem;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
/**
* #see http://stackoverflow.com/a/19749344/230513
* #see http://stackoverflow.com/a/7208723/230513
*/
public class ScatterMove extends JFrame {
private static final int N = 16;
private static final String title = "Scatter Move Demo";
private static final Random rand = new Random();
private XYSeries moved = new XYSeries("Population");
public ScatterMove(String s) {
super(s);
update();
final ChartPanel chartPanel = createDemoPanel();
this.add(chartPanel, BorderLayout.CENTER);
JPanel control = new JPanel();
control.add(new JButton(new AbstractAction("Move") {
#Override
public void actionPerformed(ActionEvent e) {
moved.clear();
update();
}
}));
this.add(control, BorderLayout.SOUTH);
}
private void update() {
for (int i = 0; i < N; i++) {
moved.add(new XYDataItem(rand.nextGaussian(), rand.nextGaussian()));
}
}
private ChartPanel createDemoPanel() {
JFreeChart jfreechart = ChartFactory.createScatterPlot(
title, "X", "Y", createSampleData(),
PlotOrientation.VERTICAL, true, true, false);
XYPlot xyPlot = (XYPlot) jfreechart.getPlot();
XYItemRenderer renderer = xyPlot.getRenderer();
NumberAxis domain = (NumberAxis) xyPlot.getDomainAxis();
domain.setRange(-3.0, 3.0);
domain.setTickUnit(new NumberTickUnit(1));
NumberAxis range = (NumberAxis) xyPlot.getRangeAxis();
range.setRange(-3.0, 3.0);
range.setTickUnit(new NumberTickUnit(1));
return new ChartPanel(jfreechart){
#Override
public Dimension getPreferredSize() {
return new Dimension(640, 480);
}
};
}
private XYDataset createSampleData() {
XYSeriesCollection xySeriesCollection = new XYSeriesCollection();
xySeriesCollection.addSeries(moved);
return xySeriesCollection;
}
public static void main(String args[]) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
ScatterMove demo = new ScatterMove(title);
demo.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
demo.pack();
demo.setLocationRelativeTo(null);
demo.setVisible(true);
}
});
}
}

How to get the coordinates of a point on mouse click with JFreeChart?

I am trying to get the coordinates of the point clicked with the mouse on a scatter plot graph.
When you click on a point, "Click event!" and the coordinates are printed on the console.
When you click on the "Test" button, "Test" and the coordinates are printed on the console.
Problem: The coordinates printed after clicking the button are up-to-date. The coordinates printed after clicking on a point are the one of the previously selected point.
How can I fix that (so when I click on a point, the coordinates of the new selected point are displayed) ?
package graph;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.util.Random;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartMouseEvent;
import org.jfree.chart.ChartMouseListener;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.axis.NumberTickUnit;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYItemRenderer;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
/**
* #see http://stackoverflow.com/questions/7231824
* #see http://stackoverflow.com/questions/7205742
* #see http://stackoverflow.com/questions/7208657
* #see http://stackoverflow.com/questions/7071057
*/
public class GraphFrameOld extends JFrame {
private static final int N = 32;
private static final String title = "Scatter Plot Pannel";
private static final Random rand = new Random();
private final XYSeries added = new XYSeries("Added");
private static XYPlot xyPlot;
public GraphFrameOld(String s) {
super(s);
final ChartPanel chartPanel = createGraphPanel();
this.add(chartPanel, BorderLayout.CENTER);
JPanel control = new JPanel();
control.add(new JButton(new AbstractAction("Add") {
#Override
public void actionPerformed(ActionEvent e) {
for (int i = 0; i < N; i++) {
added.add(rand.nextDouble(), rand.nextDouble());
}
}
}));
control.add(new JButton(new AbstractAction("Test") {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("Test");
System.out.println(xyPlot.getDomainCrosshairValue() + " "
+ xyPlot.getRangeCrosshairValue());
}
}));
// add click event
chartPanel.addChartMouseListener(new ChartMouseListener() {
#Override
public void chartMouseClicked(ChartMouseEvent e) {
System.out.println("Click event!");
XYPlot xyPlot2 = chartPanel.getChart().getXYPlot();
// Problem: the coordinates displayed are the one of the previously selected point !
System.out.println(xyPlot2.getDomainCrosshairValue() + " "
+ xyPlot2.getRangeCrosshairValue());
}
#Override
public void chartMouseMoved(ChartMouseEvent arg0) {
}
});
this.add(control, BorderLayout.SOUTH);
}
private ChartPanel createGraphPanel() {
JFreeChart jfreechart = ChartFactory
.createScatterPlot(title, "X", "Y", createSampleData(),
PlotOrientation.VERTICAL, true, true, false);
xyPlot = (XYPlot) jfreechart.getPlot();
xyPlot.setDomainCrosshairVisible(true);
xyPlot.setRangeCrosshairVisible(true);
XYItemRenderer renderer = xyPlot.getRenderer();
renderer.setSeriesPaint(0, Color.blue);
NumberAxis domain = (NumberAxis) xyPlot.getDomainAxis();
domain.setRange(0.00, 1.00);
domain.setTickUnit(new NumberTickUnit(0.1));
domain.setVerticalTickLabels(true);
NumberAxis range = (NumberAxis) xyPlot.getRangeAxis();
range.setRange(0.0, 1.0);
range.setTickUnit(new NumberTickUnit(0.1));
return new ChartPanel(jfreechart);
}
private XYDataset createSampleData() {
XYSeriesCollection xySeriesCollection = new XYSeriesCollection();
XYSeries series = new XYSeries("Random");
for (int i = 0; i < N * N; i++) {
double x = rand.nextDouble();
double y = rand.nextDouble();
series.add(x, y);
}
xySeriesCollection.addSeries(series);
xySeriesCollection.addSeries(added);
return xySeriesCollection;
}
public static void main(String args[]) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
GraphFrameOld demo = new GraphFrameOld(title);
demo.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
demo.pack();
demo.setLocationRelativeTo(null);
demo.setVisible(true);
}
});
}
}
My guess is that your mouse listener gets called before the (internal) JFreeCharts listener is, so the cross hair point is not yet updated when your code executes (point to the previous selection still). Putting your chartMouseClicked code in an invokeLater should fix that.
The problem is that the redrawing of the chart is also triggered by the mouse event and so it is not assured that this has finished at the time your event listener is triggered.
You should listen to another point which guarantees the redraw is finished. You can use the chartProgressListener and filter out when the redrawing has completed. The adapted code isn't very elegant and you might need some more checks, but it seems to do the job:
package graph;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.MouseEvent;
import java.util.Random;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartMouseEvent;
import org.jfree.chart.ChartMouseListener;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.axis.NumberTickUnit;
import org.jfree.chart.entity.ChartEntity;
import org.jfree.chart.event.*;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYItemRenderer;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
/**
* #see http://stackoverflow.com/questions/7231824
* #see http://stackoverflow.com/questions/7205742
* #see http://stackoverflow.com/questions/7208657
* #see http://stackoverflow.com/questions/7071057
*/
public class GraphFrameOld extends JFrame {
private static final int N = 32;
private static final String title = "Scatter Plot Pannel";
private static final Random rand = new Random();
private final XYSeries added = new XYSeries("Added");
private static XYPlot xyPlot;
public GraphFrameOld(String s) {
super(s);
final ChartPanel chartPanel = createGraphPanel();
this.add(chartPanel, BorderLayout.CENTER);
JPanel control = new JPanel();
control.add(new JButton(new AbstractAction("Add") {
#Override
public void actionPerformed(ActionEvent e) {
for (int i = 0; i < N; i++) {
added.add(rand.nextDouble(), rand.nextDouble());
}
}
}));
control.add(new JButton(new AbstractAction("Test") {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("Test");
System.out.println(xyPlot.getDomainCrosshairValue() + " "
+ xyPlot.getRangeCrosshairValue());
}
}));
this.add(control, BorderLayout.SOUTH);
}
private ChartPanel createGraphPanel() {
JFreeChart jfreechart = ChartFactory
.createScatterPlot(title, "X", "Y", createSampleData(),
PlotOrientation.VERTICAL, true, true, false);
xyPlot = (XYPlot) jfreechart.getPlot();
xyPlot.setDomainCrosshairVisible(true);
xyPlot.setRangeCrosshairVisible(true);
XYItemRenderer renderer = xyPlot.getRenderer();
renderer.setSeriesPaint(0, Color.red);
NumberAxis domain = (NumberAxis) xyPlot.getDomainAxis();
domain.setRange(0.00, 1.00);
domain.setTickUnit(new NumberTickUnit(0.1));
domain.setVerticalTickLabels(true);
NumberAxis range = (NumberAxis) xyPlot.getRangeAxis();
range.setRange(0.0, 1.0);
range.setTickUnit(new NumberTickUnit(0.1));
final ChartPanel result = new ChartPanel(jfreechart);
jfreechart.addProgressListener(new ChartProgressListener() {
#Override
public void chartProgress(ChartProgressEvent cpe) {
if(cpe.getType()==ChartProgressEvent.DRAWING_FINISHED){
System.out.println("Click event!");
XYPlot xyPlot2 = result.getChart().getXYPlot();
System.out.println(xyPlot2.getDomainCrosshairValue() + " "
+ xyPlot2.getRangeCrosshairValue());
}
}
});
return result;
}
private XYDataset createSampleData() {
XYSeriesCollection xySeriesCollection = new XYSeriesCollection();
XYSeries series = new XYSeries("Random");
for (int i = 0; i < N * N; i++) {
double x = rand.nextDouble();
double y = rand.nextDouble();
series.add(x, y);
}
xySeriesCollection.addSeries(series);
xySeriesCollection.addSeries(added);
return xySeriesCollection;
}
public static void main(String args[]) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
GraphFrameOld demo = new GraphFrameOld(title);
demo.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
demo.pack();
demo.setLocationRelativeTo(null);
demo.setVisible(true);
}
});
}
}
Try extracting from ChartMouseEvent e:
e.x
e.y
e.getTrigger().getX()
worked for me!
System.out.println(e.getTrigger().getX() + " " + e.getTrigger().getY() );

Categories

Resources