Hi i have a JFreeChart that i want to be able to plot and add series to without losing old data.
For example I initially generate the JFreeChart from:
public JFreeChart plot(Number[] x, Number[] y, String title, String xLabel,
String yLabel) {
XYSeries series = new XYSeries(title);
if (x.length == y.length) {
for (int i = 0; i < x.length; i++) {
series.add(x[i], y[i]);
}
XYSeriesCollection dataset = new XYSeriesCollection();
dataset.addSeries(series);
JFreeChart chart = ChartFactory.createXYLineChart(title, xLabel,
yLabel, dataset, PlotOrientation.VERTICAL, false, false,
false);
return chart;
} else {
System.out.println("Error: [plot] X&Y Vectors of different lengths");
return null;
}
}
Then i would add it to a ChartPanel and to my ContentPane:
ChartPanel cp = new ChartPanel(chart);
contentPane.add(cp, BorderLayout.CENTER);
now i need a function that can add an extra series to the plot without forgetting the series already in the dataset (so i cannot just call my plot function again)
how do I do this?
As long as you have a referance to your dataset you can add a new series at any time using dataset.addSeries(series)
Related
I have retrieved a large number of latlong values and stored in an ArrayList. I want to add markers to my MapContainer using the latlong values in the ArrayList. The challenges however is that the pins are never positioned correctly on the map (simulator and device). I have tried everything but still no success. Here is a working example. This works but the pins are positioned wrongly at runtime.
Form hi = new Form("cReporter", new BorderLayout());
hi.setScrollableY(false);
Container n = new Container(new BorderLayout());
MapContainer mc = new MapContainer();//
mc.setShowMyLocation(true);
hi.add("Center", mc);
List lx = new ArrayList();
addPoints(lx);
hi.show();
addMarkers(mc, lx);
public void addPoints(List lx)
{
Map m= new HashMap();
m.put("long", 8.993082);
m.put("lat", 38.747393);
lx.add(m);
m= new HashMap();
m.put("long", 8.988419);
m.put("lat", 38.727094);
lx.add(m);
m= new HashMap();
m.put("long", 8.991724);
m.put("lat", 38.775203);
lx.add(m);
}
public void addMarkers(MapContainer mc, List coordList)
{
Style s = new Style();
s.setFgColor(0xff0000);
s.setBgTransparency(0);
FontImage markerImg = FontImage.createMaterial(FontImage.MATERIAL_PLACE, s, 5);
for(Object m: coordList)
{
Map p= (Map)m;
Coord moscone = new Coord(Double.parseDouble(p.get("lat").toString()), Double.parseDouble(p.get("long").toString()));
mc.addMarker(EncodedImage.createFromImage(markerImg, false), mc.getCameraPosition(), "Hi marker", "Optional long description", new ActionListener() {
public void actionPerformed(ActionEvent evt) {
System.out.println("Bounding box is "+mc.getBoundingBox());
ToastBar.showMessage("You clicked the marker", FontImage.MATERIAL_PLACE);
}
});
mc.setCameraPosition(moscone);
mc.revalidate();
}
}
I'm guessing that you aren't using the correct projection lat/long values for the map as these vary based on different implementations. See this for discussion of the different types of positioning: Source event strange latitude & longitude
I notice you create a new encoded image for every marker position. This is very inefficient as every such image would take up RAM and doing it x100 could introduce a serious overhead. This is an image you should reuse.
This question already has answers here:
Making a Scatter Plot Using 2d array and JfreeChart
(1 answer)
Setting Range for X,Y Axis-JfreeChart
(2 answers)
Changing the shapes of points in scatter plot
(2 answers)
Adding points to XYSeries dynamically with JfreeChart
(1 answer)
Closed 5 years ago.
How to plot line graph using JFreeChart with two arrays: one for x coordinates and the other for y coordinates. I have two functions which gives me two arrays. I want to plot line graph with that arrays is there any possible way that I can do this.
XYSeries series = new XYSeries(" ");
for(int i=((fIndex-1)*2);i<=((tIndex*2)-1);i+=2)
{
series.add(xTValue[i],yTValue[i]);
}
XYSeriesCollection dataset = new XYSeriesCollection();
dataset.addSeries(series);
return dataset;
Can I do this as above code.
You can use
XYSeriesCollection dataset = new XYSeriesCollection();
XYSeries series = new DefaultXYSeries();
series.addSeries(" ", new double[][]{xTValue,yTValue});
dataset.addSeries(series);
JFreeChart chart = ChartFactory.createXYLineChart("My chart title",
"my x-axis label", "my y-axis label", dataset);
Alternatively, if you dont specifically need an XYLineChart, then you can do this by subclassing FastScatterPlot (I know you want a line plot, but this is an easy way in - you override the render() method to draw lines!), with something like the following:
public class LinePlot extends FastScatterPlot {
private float[] x, y;
public LinePlot(float[] x, float[] y){
super();
this.x=x;
this.y=y;
}
#Override
public void render(final Graphics2D g2, final Rectangle2D dataArea,
final PlotRenderingInfo info, final CrosshairState crosshairState) {
// Get the axes
ValueAxis xAxis = getDomainAxis();
ValueAxis yAxis = getRangeAxis();
// Move to the first datapoint
Path2D line = new Path2D.Double();
line.moveTo(xAxis.valueToJava2D(x[0], dataArea, RectangleEdge.BOTTOM),
yAxis.valueToJava2D(y[0], dataArea, RectangleEdge.LEFT));
for (int i = 1; i<x.length; i++){
//Draw line to next datapoint
line.lineTo(aAxis.valueToJava2D(x[i], dataArea, RectangleEdge.BOTTOM),
yAxis.valueToJava2D(y[i], dataArea, RectangleEdge.LEFT));
}
g2.draw(line);
}
}
This is a fairly bare-bones implementation - for example no checks that x and y have same number of points, and no addition of colour etc (e.g. g2.setPaint(myPaintColour) or line type (e.g. g2.setStroke(new BasicStroke(1.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_MITER, 10.0f, new float[] { 7, 3, 1, 3 }, 0.0f)) would give alternating -•-•-type lines)
I am trying to merge multiple graphs to create a single chart. The individual graphs have White background but somehow my merged chart end up getting gray background despite using setBackgroundpaint api.
public static String mergeXYGraphs(List<XYPlot> plots, String title, boolean legend, int width, int height) throws IOException
{
if(plots != null && !plots.isEmpty())
{
XYPlot base = plots.get(0);
for(int i = 1; i< plots.size(); i++)
{
base.setDataset(i, plots.get(i).getDataset());
base.setRenderer(i, plots.get(i).getRenderer());
}
JFreeChart chart = new JFreeChart(title, JFreeChart.DEFAULT_TITLE_FONT, base, legend);
setDateAxis(base);
chart.getXYPlot().setBackgroundPaint(Color.WHITE);
return saveImageFile(chart, "merged", "charts", width, height);
}
return "";
}
private static void setDateAxis(XYPlot plot)
{
DateAxis domainAxis = new DateAxis();
domainAxis.setAutoTickUnitSelection(true);
domainAxis.setDateFormatOverride(new SimpleDateFormat("dd/MM"));
plot.setDomainAxis(domainAxis);
}
PS : base.setBackgroundPaint(Color.WHITE); doesn't work either
So it turns out that we have to set colors on different levels on jfreechart to control the colors of different parts.
In the image above the background color of the panel is white but the background color of the chart isn't. So, I had to use:
chart.setBackgroundPaint(Color.WHITE);
Im trying to override the getItemPaint() method of XYLineAndShapeRenderer by creating a subclass:
private class MultiRenderer extends XYLineAndShapeRenderer{
#Override
public Paint getItemPaint(int row, int column) {
if(row==2){
float x = getAmplitude()[column];
return floatToColor(x);
}
return super.getItemPaint(row, column);
}
private Color floatToColor(float val){...}
}
And calling:
XYPlot xyPlot = (XYPlot) myJFreeChartObject.getPlot();
MultiRenderer r = (MultiRenderer) xyPlot.getRenderer();
But im getting a ClassCastException. Is there a way I can cast this properly or override getItemPaint without creating a subclass? Im trying to plot 2 series as regular line plots and a 3rd series without a line and different color points. The first 2 series should have a line but no point markers.
Note getAmplitude() just returns an array of floats between 0 and 1
You can either use an Anonymous Inner Class
plot.setRenderer(new XYLineAndShapeRenderer() {
#Override
public Paint getItemPaint(int row, int column) {
if(row==2){
float x = getAmplitude()[column];
return floatToColor(x);
}
return super.getItemPaint(row, column);
}
private Color floatToColor(float val){...}
});
Or use a DrawingSupplier for your plot
I am using TeeChart and the Histogram Series to display data.
I would like to color the bins individually depending on the values but all I found was the option to color each one differently. I want the bins displaying the same value to have the same color. Is that possible with TeeChart?
Yes, this is possible. You can achieve that either providing the color value when populating the series using the appropriate Add method override or using the BeforeDrawPoint event as shown here:
public Form1()
{
InitializeComponent();
InitializeChart();
}
private void InitializeChart()
{
tChart1.Aspect.View3D = false;
Histogram histogram1 = new Histogram(tChart1.Chart);
histogram1.LinePen.Visible = false;
histogram1.LinesPen.Visible = false;
for (int i = 0; i < 20; i++)
{
histogram1.Add(i);
}
histogram1.BeforeDrawPoint += histogram1_BeforeDrawPoint;
}
void histogram1_BeforeDrawPoint(Series series, BeforeDrawPointEventArgs e)
{
series.Colors[e.ValueIndex] = (series.YValues[e.ValueIndex] > 10) ? Color.Red : Color.Blue;
}