Android stacked column and linechart with MPAndroidChart doesnt center - java

I have tried the following.
Am using the MP android charts specifically the combined chart
// draw bars behind lines
mChart.setDrawOrder(new CombinedChart.DrawOrder[]{
CombinedChart.DrawOrder.BAR,
CombinedChart.DrawOrder.LINE,
});
YAxis rightAxis = mChart.getAxisRight();
rightAxis.setDrawGridLines(false);
rightAxis.setAxisMinimum(0f); // this replaces setStartAtZero(true)
YAxis leftAxis = mChart.getAxisLeft();
leftAxis.setDrawGridLines(false);
leftAxis.setAxisMinimum(0f); // this replaces setStartAtZero(true)
XAxis xAxis = mChart.getXAxis();
xAxis.setPosition(XAxis.XAxisPosition.BOTH_SIDED);
xAxis.setAxisMinimum(0f);
xAxis.setGranularity(1f);
CombinedData data = new CombinedData();
data.setData(generateLineData());
data.setData(setnewBarData());
mChart.setData(data);
So the above generates
As from the image above the values of bar chart are not centralized example the moles first bar is much to the center.
Also the line chart should be at the middle of each bar graph but it doesn't move to the middle
Where am i going wrong?
ADDITION
methods that set bar data
THe setnewBarData method is
public BarData setnewBarData() {
ArrayList<BarEntry> yVals1 = new ArrayList<BarEntry>();
for (int i = 0; i < itemcount + 1; i++) {
float mult = (itemcount + 1);
float val1 = (float) (Math.random() * mult) + mult / 3;
float val2 = (float) (Math.random() * mult) + mult / 3;
yVals1.add(new BarEntry(
i,
new float[]{val1, val2,},
getResources().getDrawable(R.drawable.back_arrow_white)));
}
BarDataSet set1;
set1 = new BarDataSet(yVals1, "Statistics Test 2018");
set1.setDrawIcons(false);
set1.setColors(new int[]{Color.rgb(61, 165, 255),Color.rgb(128, 133, 233)});
set1.setStackLabels(new String[]{"Births", "Divorces"});
set1.setAxisDependency(YAxis.AxisDependency.LEFT);
ArrayList<IBarDataSet> dataSets = new ArrayList<IBarDataSet>();
dataSets.add(set1);
BarData data = new BarData(dataSets);
data.setValueTextColor(Color.BLACK);
data.setBarWidth(0.5f);
return data;
}
THe method to generate line data is
private LineData generateLineData() {
LineData d = new LineData();
ArrayList<Entry> entries = new ArrayList<Entry>();
for (int index = 0; index < itemcount; index++)
entries.add(new Entry(index + 0.5f, getRandom(15, 5)));
LineDataSet set = new LineDataSet(entries, "Percentage Compliance");
set.setColor(Color.rgb(240, 238, 70));
set.setLineWidth(2.5f);
set.setCircleColor(Color.rgb(240, 238, 70));
set.setCircleRadius(5f);
set.setFillColor(Color.rgb(240, 238, 70));
set.setMode(LineDataSet.Mode.CUBIC_BEZIER);
set.setDrawValues(true);
set.setValueTextSize(10f);
set.setValueTextColor(Color.rgb(240, 238, 70));
set.setAxisDependency(YAxis.AxisDependency.LEFT);
d.addDataSet(set);
return d;
}

Related

XYTextAnnotation does not show up on XYPlot

I am trying to add annotations to my XYPlot; but unfortunately, they don't seem to show up.
Here is my code:
public JFreeChart createGraph() {
int[][] audiogramR = {{250, 25}, {500, 15}, {1000, 30}, {2000, 40}, {4000, 50}, {8000, 60}};
int[][] audiogramL = {{250, 60}, {500, 50}, {1000, 40}, {2000, 30}, {4000, 15}, {8000, 25}};
XYSeries r = new XYSeries("Right");
XYSeries l = new XYSeries("Left");
for (int i = 0; i <= 5; i++) { //add data to series
r.add(audiogramR[i][0], audiogramR[i][1]);
l.add(audiogramL[i][0], audiogramL[i][1]);
}
XYSeriesCollection dataset = new XYSeriesCollection(); //add series to dataset
dataset.addSeries(r);
dataset.addSeries(l);
NumberAxis yAxis = new NumberAxis("Decibels"); //create axes
LogAxis xAxis = new LogAxis("Frequency");
xAxis.setBase(2);
xAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
yAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
yAxis.setInverted(true);
yAxis.setRange(-10, 120);
Shape cross = ShapeUtilities.createDiagonalCross(3, 1);
Shape outer = new Ellipse2D.Float(-3.5f, -3.5f, 7, 7);
Shape inner = new Ellipse2D.Float(-3f, -3f, 6, 6); //shapes for plot
Area area = new Area(outer);
area.subtract(new Area(inner));
Shape ring = area;
XYPlot plot = new XYPlot(dataset, xAxis, yAxis, new XYLineAndShapeRenderer(true, true)); //create xy plot for dataset and axes
plot.getRenderer().setSeriesShape(1, cross);
plot.getRenderer().setSeriesShape(0, ring);
plot.setDomainGridlinesVisible(false);
XYTextAnnotation label = new XYTextAnnotation("Annotation text here", 50, 1024); //create annotation
plot.addAnnotation(label, true);
JFreeChart chart = new JFreeChart("Audiogram", JFreeChart.DEFAULT_TITLE_FONT, plot, true);
ChartPanel myChart = new ChartPanel(chart);
myChart.setPreferredSize(pGraph.getSize()); //size according to my window
myChart.setMouseWheelEnabled(false);
pGraph.setLayout(new java.awt.BorderLayout());
pGraph.add(myChart, BorderLayout.CENTER); //add chart to jPanel in netbeans
pGraph.validate();
}
which produces this:
Evidently, there is no annotation. Any thoughts?
As noted here,
The coordinates are specified in data space (they will be converted to Java2D space for display).
Your y value of 1024 is outside the range specified for your yAxis. As noted here, it may be useful to query the data itself for the required coordinates. In the fragment below, the series r provides the data space coordinates for the penultimate point:
double x = (double) r.getX(r.getItemCount() - 2);
double y = (double) r.getY(r.getItemCount() - 2);
XYTextAnnotation label = new XYTextAnnotation("Annotation", x, y);
plot.addAnnotation(label);

How can I set only the plot area height in XSSFChart using Apache POI 4.1.2

I have created a stacked bar chart using a template file. In my chart, there is one series and more than 100 legends. To show all legends I have adjusted the plot area Y-axis value, now the bar size bigger than expected. Are there any methods to adjust the Plot area height?
int additionalRows = barCount * barSize;
additionalRows = additionalRows + (addressList.size()/3);
chart = graphSheet.createDrawingPatriarch().createChart(new XSSFClientAnchor(100, 100, 100, 100, 1, currentIndex, 2, currentIndex+= additionalRows));
XSSFChart stackedFullBarChart = templateSheet.getDrawingPatriarch().getCharts().get(ChartType.STACKED_FULL_CHART.getValue());
chart.importContent(stackedFullBarChart);
chart.setTitleText(title);
XDDFChartData chartData = chart.getChartSeries().get(0);
XDDFDataSource<?> category = XDDFDataSourcesFactory.fromStringCellRange(dataSheet, categoryCells);
for (int i = 0; i < addressList.size(); i++) {
XDDFNumericalDataSource<?> values = XDDFDataSourcesFactory.fromNumericCellRange(dataSheet, addressList.get(i));
int seriesNameRow = addressList.get(i).getFirstRow() - 2;
int seriesNameCol = addressList.get(i).getFirstColumn();
XSSFCell seriesNameCell = dataSheet.getRow(seriesNameRow).getCell(seriesNameCol);
String seriesName = seriesNameCell.getStringCellValue();
if (i >= chartData.getSeriesCount()) {
XDDFChartData.Series series1 = chartData.addSeries(category, values);
series1.setTitle(seriesName, new CellReference(seriesNameCell));
} else {
chartData.getSeries(i).setTitle(seriesName, new CellReference(seriesNameCell));
chartData.getSeries(i).replaceData(category, values);
}
}
chart.getOrAddManualLayout().setWidthRatio(0.8);
**chart.getOrAddManualLayout().setHeightRatio(0.9);
chart.getOrAddManualLayout().setY(1.1);**
chart.plot(chartData);
chart.getOrAddLegend().setPosition(LegendPosition.TOP);
CTLegend ctLegend = chart.getCTChart().addNewLegend();
ctLegend.addNewLegendPos().setVal(STLegendPos.T);
CTBoolean ctBoolean = CTBoolean.Factory.newInstance();
ctBoolean.setVal(false);
ctLegend.setOverlay(ctBoolean);
CTDouble ctdouble = CTDouble.Factory.newInstance();
ctdouble.setVal(0.1);
chart.getCTChart().getPlotArea().getLayout().getManualLayout().setH(ctdouble);
Expected Output:

How to solve this error - i want create MPAndroidChart dynamic multiple line

i tried MPAndroidChart dynamic multiple line
private LineChart mChart;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mChart = (LineChart) findViewById(R.id.chart1);
mChart.setDrawGridBackground(false);
mChart.setDescription("");
mChart.setNoDataTextDescription("You need to provide data for the chart.");
mChart.setTouchEnabled(true);
mChart.setDragEnabled(true);
mChart.setScaleEnabled(true);
mChart.setPinchZoom(true);
LimitLine llXAxis = new LimitLine(10f, "Index 10");
llXAxis.setLineWidth(4f);
llXAxis.enableDashedLine(10f, 10f, 0f);
llXAxis.setLabelPosition(LimitLine.LimitLabelPosition.RIGHT_BOTTOM);
llXAxis.setTextSize(10f);
XAxis xAxis = mChart.getXAxis();
xAxis.enableGridDashedLine(10f, 10f, 0f);
YAxis leftAxis = mChart.getAxisLeft();
leftAxis.removeAllLimitLines();
leftAxis.enableGridDashedLine(10f, 10f, 0f);
leftAxis.setDrawZeroLine(false);
leftAxis.setDrawLimitLinesBehindData(true);
mChart.getAxisRight().setEnabled(false);
float[] lineData_0 = {37500, 38000, 38500, 39000, 39500, 40000, 40500};
float[] lineData_1 = {3000, 3500, 3800, 3600, 3400, 2000, 2800};
float[] lineData_2 = {0, 0, 6000, 25000, 24800, 24750, 5000};
float[] lineData_3 = {0, 6500, 11000, 12500, 13000, 14000, 2000};
float[] lineData_4 = {0, 9000, 12400, 12450, 9300, 8000, 6000};
float[][] all_line_data = {lineData_0, lineData_1, lineData_2, lineData_3, lineData_4};
ArrayList<ILineDataSet> dataSets = null;
ArrayList<Entry>[] values = (ArrayList<Entry>[]) new ArrayList[all_line_data.length];
for (int j = 0; j < all_line_data.length; j++) {
for (int i = 0; i < all_line_data[j].length; i++) {
values[j].add(new Entry(all_line_data[j][i], i));
}
LineDataSet[] set0 = new LineDataSet[j];
set0[j].enableDashedLine(10f, 5f, 0f);
set0[j].enableDashedHighlightLine(10f, 5f, 0f);
set0[j].setColor(Color.BLACK);
set0[j].setCircleColor(Color.BLACK);
set0[j].setLineWidth(1f);
set0[j].setCircleRadius(3f);
set0[j].setDrawCircleHole(false);
set0[j].setValueTextSize(9f);
set0[j].setDrawFilled(true);
dataSets = new ArrayList<ILineDataSet>();
dataSets.add(set0[j]);
}
LineData data = new LineData(dataSets);
mChart.setData(data);
}
I am getting the following error....
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'boolean java.util.ArrayList.add(java.lang.Object)' on a null object reference
i solved this problem
LineChart mChart = (LineChart) findViewById(R.id.chartLine);
mChart.setDrawGridBackground(true);
// no description text
mChart.setDescription("");
mChart.setNoDataTextDescription("You need to provide data for the chart.");
// enable touch gestures
mChart.setTouchEnabled(true);
// enable scaling and dragging
mChart.setDragEnabled(true);
mChart.setScaleEnabled(true);
// if disabled, scaling can be done on x- and y-axis separately
mChart.setPinchZoom(true);
CustomMarkerView mv = new CustomMarkerView (MainActivity.this, R.layout.line_graph_marker_view, colors);
mChart.setMarkerView(mv);
// x-axis limit line
LimitLine llXAxis = new LimitLine(10f, "Index 10");
llXAxis.setLineWidth(4f);
llXAxis.setLabelPosition(LimitLine.LimitLabelPosition.RIGHT_BOTTOM);
llXAxis.setTextSize(10f);
XAxis xAxis = mChart.getXAxis();
xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);
YAxis leftAxis = mChart.getAxisLeft();
leftAxis.removeAllLimitLines(); // reset all limit lines to avoid overlapping lines
leftAxis.setAxisMinValue(0);
leftAxis.setDrawZeroLine(true);
// limit lines are drawn behind data (and not on top)
leftAxis.setDrawLimitLinesBehindData(true);
mChart.getAxisRight().setEnabled(false);
float[] lineData_0 = {37500, 38000, 38500, 39000, 39500, 40000, 40500};
float[] lineData_1 = {3000, 3500, 3800, 3600, 3400, 2000, 2800};
float[] lineData_2 = {0, 0, 6000, 25000, 24800, 24750, 5000};
float[] lineData_3 = {0, 6500, 11000, 12500, 13000, 14000, 2000};
float[] lineData_4 = {0, 9000, 12400, 12450, 9300, 8000, 6000};
float[][] all_line_data = {lineData_0, lineData_1, lineData_2, lineData_3, lineData_4};
int[] graph_linear_background = {R.drawable.graph_background_0, R.drawable.graph_background_1, R.drawable.graph_background_2, R.drawable.graph_background_3, R.drawable.graph_background_4};
int[] graph_linear_point_color = {Color.rgb(100, 199, 255), Color.rgb(109, 220, 124), Color.rgb(236, 91, 102), Color.rgb(184, 85, 240), Color.rgb(70, 119, 191)};
List<ArrayList<Entry>> values_all = new ArrayList<ArrayList<Entry>>();
for (int k = 0; k < all_line_data.length; k++) {
ArrayList<Entry> list = new ArrayList<>();
for (int i = 0; i < all_line_data[k].length; i++) {
list.add(new Entry(i, all_line_data[k][i]));
}
values_all.add(list);
}
ArrayList<ILineDataSet> dataSets = new ArrayList<ILineDataSet>();
String[] arr = new String[]{"a", "b", "c", "d", "e", "f"};
Map<String, LineDataSet> map = new HashMap<>();
for(int i = 0; i < all_line_data.length; i++) {
map.put("set0" + i, new LineDataSet(values_all.get(i), arr[i]));
// set the line to be drawn like this "- - - - - -"
map.get("set0" + i).setColor(graph_linear_point_color[i]);
map.get("set0" + i).setCircleColor(graph_linear_point_color[i]);
map.get("set0" + i).setLineWidth(3f);
map.get("set0" + i).setDrawValues(false);
map.get("set0" + i).setCircleRadius(4f);
map.get("set0" + i).setDrawCircleHole(false);
map.get("set0" + i).setDrawFilled(true);
dataSets.add(map.get("set0" + i));
if (Utils.getSDKInt() >= 18) {
// fill drawable only supported on api level 18 and above
Drawable drawable = ContextCompat.getDrawable(this, graph_linear_background[i]);
map.get("set0" + i).setFillDrawable(drawable);
} else {
map.get("set0" + i).setFillColor(Color.TRANSPARENT);
}
}
// create a data object with the datasets
LineData line_data = new LineData(dataSets);
// set data
mChart.setData(line_data);
output is....

How to plot a dual Y-Axis (secondary Y-axis) using AChartEngine - Android

I have two data series with two different Y-axis and a single X-axis. I am trying to plot a Dual Y-Axis (or in Excel known as Secondary Y-Axis) so that the chart are scaled. But I only get a single Y-axis for both data series. Note: I am using AChartEngine 1.1.0
Can anyone please advise.
My code is given below with a screenshot.
public class LineChart {
public Intent getIntent(Context context){
int[] x = {1,2,3,4,5,6,7,8,9,10};
int[] y = {22,45,34,45,55,65,74,85,93,100};
TimeSeries series = new TimeSeries("Data1");
for(int i = 0; i<x.length; i++){
series.add(x[i], y[i]);
}
int[] x2 = {1,2,3,4,5,6,7,8,9,10};
int[] y2 = {223,454,334,454,554,655,745,855,935,510};
TimeSeries series2 = new TimeSeries("Data2");
for(int i = 0; i<x.length; i++){
series2.add(x2[i], y2[i]);
}
//Multiple Series Data Set
XYMultipleSeriesDataset dataset = new XYMultipleSeriesDataset();
dataset.addSeries(series); //First Data Series
dataset.addSeries(series2); //Second Data Series
//Multiple Series Renderer
XYMultipleSeriesRenderer mRenderer = new XYMultipleSeriesRenderer(2);
//Background
mRenderer.setApplyBackgroundColor(true);
mRenderer.setBackgroundColor(Color.BLACK);
//mRenderer.setMarginsColor(Color.parseColor("#F5F5F5"));
//Grid
mRenderer.setShowGridY(true);
mRenderer.setShowGridX(true);
mRenderer.setGridColor(Color.WHITE);
//Label
mRenderer.setLabelsTextSize(14);
mRenderer.setXLabelsColor(Color.GREEN);
//Min and Max
mRenderer.setXAxisMax(series.getMaxX());
mRenderer.setXAxisMin(series.getMinX());
//Dual yaxis
mRenderer.setYLabelsColor(0, Color.GREEN);
mRenderer.setYLabelsColor(1, Color.RED);
mRenderer.setYTitle("Y-AXIS1", 0);
mRenderer.setYTitle("Y-AXIS2", 1);
mRenderer.setYAxisAlign(Align.LEFT, 0);
mRenderer.setYAxisAlign(Align.RIGHT, 1);
mRenderer.setYLabelsAlign(Align.LEFT, 0);
mRenderer.setYLabelsAlign(Align.RIGHT, 1);
//First Series - Single Series Renderer
XYSeriesRenderer renderer = new XYSeriesRenderer();
renderer.setColor(Color.RED);
renderer.setPointStyle(PointStyle.CIRCLE);
renderer.setFillPoints(true);
//Second Series - Single Series Renderer
XYSeriesRenderer renderer2 = new XYSeriesRenderer();
renderer2.setColor(Color.GREEN);
renderer2.setPointStyle(PointStyle.CIRCLE);
renderer2.setFillPoints(true);
//Add renderers to multiple series Renderer
mRenderer.addSeriesRenderer(renderer);
mRenderer.addSeriesRenderer(renderer2);
Intent intent = ChartFactory.getLineChartIntent(context, dataset, mRenderer, "Line Graph Title");
return intent;
}
}
Finally, I have done it using this example - here

XYTextAnnotation in DynamicTimeSeriesCollection

I'm trying to implement XYTextAnnotation in DynamicTimeSeriesCollection.
I have no idea how to find X value of series in DynamicTimeSeriesCollection. My code so far:
DynamicTimeSeriesCollection dataset = new DynamicTimeSeriesCollection(1, 60, new Minute());
final JFreeChart result = ChartFactory.createTimeSeriesChart(TITLE, "A", "B", dataset, true, true, false);
float[] series1Small = new float[10];
dataset.setTimeBase(new Minute(1, 1, 1, 1, 2013));
dataset.addSeries(series1Small,0,"1");
JFreeChart result = ChartFactory.createTimeSeriesChart(TITLE, "Время", "Платежи", dataset, true, true, false);
final XYPlot plot = result.getXYPlot();
-----------------------------------------------------------Below line doesn't work.
TimeSeriesDataItem item1 = series1.getDataItem(series1.getItemCount() - 1);
createAnnotation(item1,plot);
This is a function that used to work for annotation with TimeSeriesCollection.
public static void createAnnotation(TimeSeriesDataItem item,XYPlot plot)
{
double xAnnotation = item.getPeriod().getFirstMillisecond();
double yAnnotation = item.getValue().doubleValue();
XYTextAnnotation annotation = new XYTextAnnotation(item.getValue().toString(), xAnnotation, yAnnotation);
annotation.setFont(new Font("Arial",Font.BOLD,11));
plot.addAnnotation(annotation);
}
Starting form this example, I added the following lines in createChart() to obtain the image below:
double x = dataset.getXValue(0, COUNT - 1);
double y = dataset.getYValue(0, COUNT - 1);
String s = dataset.getY(0, COUNT - 1).toString();
XYTextAnnotation a = new XYTextAnnotation(s, x, y);
a.setFont(a.getFont().deriveFont(24f));
plot.addAnnotation(a);

Categories

Resources