ClassCastException when trying to extend XYLineAndShapeRenderer (JFreeChart) - jfreechart

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

Related

How to plot XYLineChart graph using two arrays: one for x and y coordinates [duplicate]

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)

jfreechart setBackgroundpaint not working

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

WPF Toolkit Chart Unordered LineSeries

The default LineSeries implementation orders data points by independed value. This gives me strange results for data like this:
Is it possible to plot a line series where lines are drawn between the points in the original order?
I currently solved this by inheriting from LineSeries:
class UnorderedLineSeries : LineSeries
{
protected override void UpdateShape()
{
double maximum = ActualDependentRangeAxis.GetPlotAreaCoordinate(
ActualDependentRangeAxis.Range.Maximum).Value;
Func<DataPoint, Point> PointCreator = dataPoint =>
new Point(
ActualIndependentAxis.GetPlotAreaCoordinate(
dataPoint.ActualIndependentValue).Value,
maximum - ActualDependentRangeAxis.GetPlotAreaCoordinate(
dataPoint.ActualDependentValue).Value);
IEnumerable<Point> points = Enumerable.Empty<Point>();
if (CanGraph(maximum))
{
// Original implementation performs ordering here
points = ActiveDataPoints.Select(PointCreator);
}
UpdateShapeFromPoints(points);
}
bool CanGraph(double value)
{
return !double.IsNaN(value) &&
!double.IsNegativeInfinity(value) &&
!double.IsPositiveInfinity(value) &&
!double.IsInfinity(value);
}
}
Result:
It's worth pointing out that, to use #hansmaad's suggestion above, you will need to create a new namespace and point your XAML to this, rather than the assembly.
i.e.
XAML:
xmlns:chart="clr-namespace:MyApplication.UserControls.Charting"
C#:
using System.Windows.Controls.DataVisualization.Charting;
using System.Windows;
namespace MyApplication.UserControls.Charting {
class Chart : System.Windows.Controls.DataVisualization.Charting.Chart {}
class UnorderedLineSeries : LineSeries {
....
}
}

TeeChart WPF Histogram color of bins

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

Using Sencha GXT 3, generate a line chart populated with a dynamic number of line series fields?

Using Sencha GXT 3.0 is it possible to generate a line chart and populate it with a dynamic number of line series fields, and if so, what is the recommended method?
I know multiple series fields can be added to a chart, but the line chart examples (and the other chart examples for that matter) make use of an interface which extends PropertyAccess<?> and the interface specifies a static number of expected fields (e.g. data1(), data2(), data3(), etc.). If the interface is to be used to specify the fields to add to the chart, how could you account for a chart which may require n number of fields (i.e. n number of line series on a given chart).
Example provided on Sencha's site:
http://www.sencha.com/examples/#ExamplePlace:linechart
I ran into the same issue. It would be a much nicer design if each series had a store instead of having one store per chart.
I had one long list of metric values in metricDataStore. Each metric value has a description. I wanted all the metric values with the same description displayed on one (and only one) series. I had my value providers for each series return null for both the x and y axis if the value wasn't supposed to be in the series.
This seems like a hack to me but it works for my usage:
myChart = new Chart<MetricData>();
myChart.setStore(metricDataStore);
.
.
.
for (MetricInfo info : metricInfoData) {
LineSeries<MetricData> series = new LineSeries<MetricData>();
series.setChart(myChart);
series.setSmooth(false);
series.setShownInLegend(true);
series.setHighlighting(true);
series.setYAxisPosition(Chart.Position.LEFT);
series.setYField(new MetricValueProvider(info.getName()));
series.setXAxisPosition(Chart.Position.BOTTOM);
series.setXField(new MetricTimeProvider(info.getName()));
myChart.addSeries(series);
}
.
.
.
private class MetricTimeProvider extends Object implements ValueProvider<MetricData, Long> {
private String metricName;
public MetricTimeProvider(String metricName) {
this.metricName = metricName;
}
#Override
public Long getValue(MetricData m) {
if (metricName != null && metricName.equals(m.getLongDesc()))
return m.getId();
else
return null;
}
#Override
public void setValue(MetricData m, Long value) {
}
#Override
public String getPath() {
return null;
}
}
private class MetricValueProvider extends Object implements ValueProvider<MetricData, Double> {
private String metricName;
public MetricValueProvider(String metricName) {
this.metricName = metricName;
}
#Override
public Double getValue(MetricData m) {
if (metricName != null && metricName.equals(m.getLongDesc()))
return m.getMetricValue();
else
return null;
}
#Override
public void setValue(MetricData m, Double value) {
}
#Override
public String getPath() {
return null;
}
}

Resources