Date Chart in aChartEngine - java

I have edited my question...
Here is the code I am using, I am adding weight of an animal with time.
else if (str.equals("Weight"))
{
mDbHelper.open();
wtArray = mDbHelper.getWeight();
mDbHelper.close();
TimeSeries diaSeries = new TimeSeries("Weight");
for ( int i =0; i <wtArray.size(); i++)
{
Weight wt = wtArray.get(i);
diaSeries.add(wt.date, wt.weight);
}
XYMultipleSeriesDataset dataset = new XYMultipleSeriesDataset();
dataset.addSeries(diaSeries);
XYMultipleSeriesRenderer mrenderer = new XYMultipleSeriesRenderer();
XYSeriesRenderer renderer = new XYSeriesRenderer();
renderer.setColor(Color.RED);
renderer.setPointStyle(PointStyle.DIAMOND);
renderer.setFillPoints(true);
mrenderer.addSeriesRenderer(renderer);
graphLayout.addView(ChartFactory.getTimeChartView(this, dataset, mrenderer, "MM/dd/yyyy"));
}
It never shows any value on x axis, i-e time. I am using LinearLayout. Kindly tell me what is wrong. Also no Graph line is showing.
Secondly, What If I want to show data from specific date to another date?

You have two options here:
You keep using a LineChart and add custom labels while disabling the regular ones:
renderer.setXLabels(0);
renderer.addXTextLabel(date.getTime(), "Label");
You use a TimeChart which is a LineChart displaying time values using a format provided by you, instead of the LineChart.

umar.
Check my following code. I use a TimeChart here.
XYMultipleSeriesRenderer renderer = buildRenderer(colors, styles);
// mDateFrom and mDateTo are Date Objects
// Set the date span here
setChartSettings(renderer, "title", "x_tiele", "y_title",
mDateFrom.getTime(),
mDateTo.getTime(), 0, 1, Color.GRAY, Color.LTGRAY);
XYMultipleSeriesDataset dataset = buildDateDataset(titles, mHashMapGroupedEntites);
return ChartFactory.getTimeChartView(context, dataset,
renderer, "yyyy/MM/dd HH"+":00:00");
Try this.
XYMultipleSeriesDataset dataset = new XYMultipleSeriesDataset();
dataset.addSeries(diaSeries);
XYMultipleSeriesRenderer mrenderer = new XYMultipleSeriesRenderer();
mrenderer.setXAxisMin(YOUR_DATE_MIN);
mrenderer.setXAxisMax(YOUR_DATE_MAX);
// XYSeriesRenderer renderer = new XYSeriesRenderer();
mrenderer.setColor(Color.RED);
mrenderer.setPointStyle(PointStyle.DIAMOND);
mrenderer.setFillPoints(true);
// mrenderer.addSeriesRenderer(renderer);
graphLayout.addView(ChartFactory.getTimeChartView(this, dataset, mrenderer, "MM/dd/yyyy"));

Related

MPAndroidChart customizing horizontal BarChart

Here is a picture of the barchart. As you can see there is an alignment issue, the bars are not aligning with the labels particularly in the mid section. In addition I want the bottom Axis to show the bars in 10's not 1.2, 1.4, 1.6 etc as there will never be any decimals so its not useful. I would also like the value of each bar to be shown at the end as a number to show the total count for each bar.
Picture of chart
https://imgur.com/gallery/ThHx1eJ
Styling
// All JSON entries form the MYSQL server are parsed into an ArrayList.
moodEntries = new ArrayList<>();
// For loop which dynamically adds all entries to the ArrayList
for (MoodStatsPieChartModel moodLogPieChartResponse : moodStatsPieChartModels) {
moodEntries.add(new BarEntry(moodLogPieChartResponse.getMoodBefore(), moodLogPieChartResponse.getMoodCount()));
}
-- the .getmoodBefore() will be an int value from 1 - 18 which represents a mood
and the .getmoodCount() just totals how much of each mood.
This data is stored in the internal sqlite database.
}
// custom X-axis labels
String[] values = new String[] { "Excited", "Happy", "Confident", "Proud", "Content", "Fine", "Relaxed", "Calm", "Tired", "Guilty", "Sad", "Depressed", "Embarrassed", "Upset", "Stressed", "Anxious", "Confused", "Disgusted"};
BarDataSet barDataSet = new BarDataSet(moodEntries, "");
barDataSet.setColors(color);
barDataSet.setValueTextSize(16f);
barDataSet.setValueTextColor(Color.BLACK);
BarData data = new BarData(barDataSet);
//barData.setBarWidth(1f);
data.setValueTextSize(10f);
XAxis xAxis = chart.getXAxis();
xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);
xAxis.setLabelCount(values.length, true);
xAxis.setDrawLabels(true);
xAxis.setCenterAxisLabels(true);
xAxis.setValueFormatter(new MyXAxisValueFormatter(values));
xAxis.setGranularity(10f);
//xAxis.setGranularityEnabled(true);
//xAxis.setDrawGridLines(false);
//xAxis.setDrawAxisLine(false);
//xAxis.setDrawLabels(true);
//xAxis.setAxisMaximum(values.length);
//barChart.getXAxis().setDrawGridLines(false);
//xAxis.setAxisMinimum(values.length);
// Top Axis
YAxis yAxis = chart.getAxisLeft();
yAxis.setDrawAxisLine(false);
yAxis.setDrawGridLines(false);
//yAxis.setGranularity(1f);
yAxis.setDrawLabels(false);
//yAxis.setAxisMaximum(0f);
//yAxis.setDrawGridLinesBehindData(false);
// Bottom Axis
YAxis yAxisBottom = chart.getAxisRight();
yAxisBottom.setDrawGridLines(false);
yAxisBottom.setDrawAxisLine(false);
//yAxisBottom.setGranularity(10f);
//yAxisBottom.setDrawGridLinesBehindData(false);
//yAxisBottom.setDrawLabels(true);
//yAxisBottom.setAxisMinimum(2f);
Legend l = chart.getLegend();
l.setEnabled(false);
chart.setVisibility(View.VISIBLE);
chart.animateXY(1000, 1000);
chart.getDescription().setEnabled(false);
chart.setExtraOffsets(-10, -10, -10, -10);
chart.setDrawGridBackground(false);
chart.setDrawBarShadow(false);
chart.setDrawValueAboveBar(true);
//chart.setFitBars(true);
//chart.setMaxVisibleValueCount(100);
chart.setData(data);
chart.invalidate();
You can try this:
public class ValFormatter extends ValueFormatter {
#Override
public String getFormattedValue(float value) {
if(value == Math.round(value)){ // value is an integer?
return String.valueOf((int) value);
}else{
return "";
}
}
}
and
yAxisBottom.setValueFormatter(new ValFormatter())
Because yAxis shows you a range. This way you can fix it.
You can try these lines for value of bar:
data.setValueTextSize(10f)
data.setDrawValues(true)

Too much data in DomainAxis, another way of setTickUnit

I am creating chart like this:
DefaultCategoryDataset cumulativeResultData = new DefaultCategoryDataset();
DefaultCategoryDataset indexResultData = new DefaultCategoryDataset();
then in for loop im adding data to each Dataset using cumulativeResultData.addValue
CategoryPlot plot = new CategoryPlot();
plot.setDomainAxis(new CategoryAxis("Days"));
plot.setRangeAxis(new NumberAxis("Result"));
plot.setOrientation(PlotOrientation.VERTICAL);
CategoryAxis domainAxis = plot.getDomainAxis();
domainAxis.setCategoryLabelPositions(CategoryLabelPositions.UP_45);
LineAndShapeRenderer renderer2 = new LineAndShapeRenderer(true, false);
LineAndShapeRenderer renderer = new LineAndShapeRenderer(true, false);
plot.setRenderer(renderer);
plot.setDataset(cumulativeResultData);
ValueAxis rangeAxis2 = new NumberAxis("Index price");
rangeAxis2.setRange(minRange - 1, maxRange + 1);
plot.setRangeAxis(1, rangeAxis2);
plot.setRenderer(1, renderer2);
plot.setDataset(1, indexResultData);
plot.mapDatasetToRangeAxis(1, 1);
JFreeChart chart = new JFreeChart(plot);
But what i get is not what i expected to get, please take a look in the picture bellow.
The domainAxis has to much data and it is blurred. Is any way to repair this? That only every for example 20th element shows on the domainAxis?
http://imgur.com/PkxSZl8
You should only use the CategoryPlot class when your x-axis will show categorical data. It looks like you have time series data, and for that you can use the XYPlot class with a DateAxis for the x-axis. There is also the TimeSeriesCollection class that you can probably use for your dataset.

JFreeChart not updating

Some background info: I'm creating a system to register lost, found and returned luggage. The amount of those 3 variable need to be in a LineChart to get a nice overview from how much luggage is lost etc. over an amount of time.
Now the problem:
When I create a LineChart and add it to a ChartPanel the LineChart represent a dataset. I've heard that when you edit/update your dataset, the chart is also automatically updated. Well I have an update button next to the chart which has to update the chart when clicked. Independent of the chart in an already existing JPanel/ChartPanel I also create a new frame which represent a ChartFrame.
When I click the update button a new frame pops-up and with the most recent data from the updated dataset. When I click it again, obviously another frame is created, but the already existing frame is also update while the chart in the JPanel isn't though they use the same dataset which is static and comes from a LineChart model.
Well here some code:
LineChartModel
//At the top of the document the dataset is initialize static
public static DefaultCategoryDataset dataset = null;
/*****************Other code omitted***********************/
/**
*
* Updates an already existing dataset
*
* #param dataset
* #return dataset
*/
public CategoryDataset updateDataset(DefaultCategoryDataset dataset) {
this.dataset = dataset;
// row keys...
final String rowLost = "Lost";
final String rowFound = "Found";
final String rowReturned = "Returned";
//Don't pay attention to this. It's setting the value for the dataset from different arrays which I know of the are filled correctly
int i = 0;
while (i < 12) {
dataset.setValue(lost[i], rowLost, type[i]);
System.out.println("There were " + lost[i]
+ " lost luggages in month: " + type[i]);
i++;
}
for (int j = 0; j < 12; j++) {
dataset.setValue(found[j], rowFound, type[j]);
System.out.println("There were " + found[j]
+ " found luggages in month: " + type[j]);
}
for (int j = 0; j < 12; j++) {
dataset.setValue(returned[j], rowReturned, type[j]);
System.out.println("There were " + returned[j]
+ " returned luggages in month: " + type[j]);
}
return dataset;
}
The LineChart Class with his constructor
LineChartModel model = new LineChartModel();
public ChartPanel chartPanel;
/**
* Creates a new demo.
*
* #param title the frame title.
*/
public LineChart(final String title, LineChartModel m) {
m = model;
m.selectRange();
m.createDataset();
final JFreeChart chart = createChart(m.dataset);
chartPanel = new ChartPanel(chart);
chartPanel.setPreferredSize(new Dimension(500, 270));
}
ChartController
First the params of the constructor
public ChartController(final ManCharts v, final LineChartModel m) {
view = v;
model = m;
And here the actionlistener of the button.
//Select a range by sumbitting the variables
v.date.btnSubmit.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
//selectRange select all the data between 2 dates but isn't important for this problem
m.selectRange(/*v.date.dateChooserFrom, v.date.dateChooserTo*/);
//updateDataset updates the dataset from the LineChartModel which is static
m.updateDataset(m.dataset);
//The data in the chart should already be updated but here I'm trying to replace the current chart by a new one
v.chart.chartPanel = new ChartPanel(v.chart.createChart(m.dataset));
//This is the new chart which does automatically update when the button is pressed
JFreeChart chart = ChartFactory.createLineChart("Something chart", "Date", "Value", m.dataset);
ChartFrame frame = new ChartFrame("New line chart", chart);
frame.setVisible(true);
}
});
I really hope someone can help and that this problem is not too complicated without having the full code.
If you need more code or something. Just say so.
Thanks in advance!
EDIT!
I think it has to do something with how I create the chart. The chart in my JPanel which is created at the start of my application is created with an edited method (this is part of my LineChart class and stands below my constructor):
/**
* Creates a sample chart.
*
* #param dataset a dataset.
*
* #return The chart.
*/
public JFreeChart createChart(final CategoryDataset dataset) {
// create the chart...
final JFreeChart chart = ChartFactory.createLineChart(
"Luggage", // chart title
"Time", // domain axis label
"Value", // range axis label
dataset, // data
PlotOrientation.VERTICAL, // orientation
true, // include legend
true, // tooltips
false // urls
);
chart.setBackgroundPaint(Color.decode("#d6d9df"));
final CategoryPlot plot = (CategoryPlot) chart.getPlot();
plot.setBackgroundPaint(Color.lightGray);
plot.setRangeGridlinePaint(Color.white);
// customise the range axis...
final NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis();
rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
rangeAxis.setAutoRangeIncludesZero(true);
// customise the renderer...
final LineAndShapeRenderer renderer = (LineAndShapeRenderer) plot.getRenderer();
//renderer.setDrawShapes(true);
renderer.setSeriesStroke(
0, new BasicStroke(
2.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND,
1.0f, new float[] {10.0f, 6.0f}, 0.0f
)
);
renderer.setSeriesStroke(
1, new BasicStroke(
2.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND,
1.0f, new float[] {6.0f, 6.0f}, 0.0f
)
);
renderer.setSeriesStroke(
2, new BasicStroke(
2.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND,
1.0f, new float[] {2.0f, 6.0f}, 0.0f
)
);
// OPTIONAL CUSTOMISATION COMPLETED.
return chart;
}
SOLVED
It had to do with another dataset that was created when clicking the submit button. So I've fixed the recreation and it's working now. Not really a chart problem, but just a problem in my model. Thanks for the help anyway!
ChartPanel implements an event listener that prompts it to repaint() itself when needed; JPanel does not. See the implementation of ChartChangeListener in chartChanged(), for example. When debugging, look for one instance of ChartPanel that shadows another or an errant use of JPanel.
Addednum Does the frame also need to be an ApplicationFrame or could it work in a JFrame?
Either is acceptable, as shown in this JFrame example or this ApplicationFrame example; both update dynamically. Note that Swing GUI objects should be constructed and manipulated only on the event dispatch thread.

Java JFreeChart Category Step Chart horizontal (image to explane)

i need the following type of chart:
It should be a "steped" line chart with categories on the vertical axis, like this:
I found this example of an Category Step Chart, but it the orientation is not right for my purpose.
http://www.jfree.org/jfreechart/api/javadoc/org/jfree/chart/renderer/category/CategoryStepRenderer.html
All i have done so far is this, but as you can see the red line does not fit to the orientation of the chart(should be horizontal):
The corresponding code to this:
DefaultCategoryDataset ds = new DefaultCategoryDataset();
// create dataset
for (int k = 0; k < ffCount; k++) {
StateSignal ss1 = (StateSignal) this.ffDSet.getFframes().get(k).getSignals().get(i);
ds.setValue((double) k + 1, ss1.getName(), ss1.getStates().get(0).getStatus());
}
CategoryStepRenderer categorysteprenderer = new CategoryStepRenderer(false);
categorysteprenderer.setBaseToolTipGenerator(new StandardCategoryToolTipGenerator());
CategoryAxis categoryaxis = new CategoryAxis("Category");
NumberAxis numberaxis = new NumberAxis("Value");
CategoryPlot categoryplot = new CategoryPlot(ds, categoryaxis, numberaxis, categorysteprenderer);
categoryplot.setRangePannable(true);
categoryplot.setOrientation(PlotOrientation.HORIZONTAL);
chart = new JFreeChart("test", null, categoryplot, true);
I donĀ“t get it to work. Any ideas?
Thanks in advance!
It looks like you need to use a standard XYLineChart with a XYStepRenderer and a SymbolAxis to replace the default Range Axis rather than a CategoryStepRenderer and a horizontal plot orientation
If you associate Status A and B with a numerical value say 1 and 2 you can create a chart like this:
Using this a XYStepRenderer
XYStepRenderer renderer = new XYStepRenderer();
renderer.setBaseShapesVisible(true);
renderer.setSeriesStroke(0, new BasicStroke(2.0f));
renderer.setSeriesStroke(1, new BasicStroke(2.0f));
renderer.setBaseToolTipGenerator(new StandardXYToolTipGenerator());
renderer.setDefaultEntityRadius(6);
plot.setRenderer(renderer);
and a Symbol Axis
String[] grade = new String[3];
grade[0] = "";
grade[1] = "Status A";
grade[2] = "Status B";
SymbolAxis rangeAxis = new SymbolAxis("", grade);
rangeAxis.setTickUnit(new NumberTickUnit(1));
rangeAxis.setRange(0,3);
plot.setRangeAxis(rangeAxis);
In this example the SymbolAxis provides an alternative label for each value in the Axis

display numbers on pie chart

I've developed an android application to display a pie chart. I have used the achartengine library to do this.
With this code below I get the pie chart output with 3 portions labeled as mentioned in categorySeries. I want to display the percentage values on the pie diagram. How can i do this?
public static final GraphicalView getPieChartView(Context context,
CategorySeries dataset, DefaultRenderer renderer) {
checkParameters(dataset, renderer);
PieChart chart = new PieChart(dataset, renderer);
return new GraphicalView(context, chart);
}
private static void checkParameters(CategorySeries dataset,
DefaultRenderer renderer) {
if (dataset == null
|| renderer == null
|| dataset.getItemCount() != renderer
.getSeriesRendererCount()) {
throw new IllegalArgumentException(
"Dataset and renderer should be not null and the dataset number of items should be equal to the number of series renderers");
}
}
and this is my onCreate method
Bundle bundle = getIntent().getExtras();
int highc = bundle.getInt("high");
int lowc = bundle.getInt("low");
int medc = bundle.getInt("medium");
RelativeLayout layout = (RelativeLayout) findViewById(R.id.relativestatsLayout);
TextView message = (TextView) findViewById(R.id.statText);
message.setText("\n\n\tTickets Summary");
message.setGravity(50);
//layout.addView(message);
//setContentView(message);
int[] colors = new int[] { Color.rgb(255, 0, 0),Color.rgb(220, 51,51), Color.rgb(255, 191, 0) };
DefaultRenderer renderer = buildCategoryRenderer(colors);
CategorySeries categorySeries = new CategorySeries("Tickets Chart");
categorySeries.getTitle();
categorySeries.add("critical", highc);
categorySeries.add("major ", medc);
categorySeries.add("minor ", lowc);
layout.addView(getPieChartView(this, categorySeries, renderer));
}
protected DefaultRenderer buildCategoryRenderer(int[] colors) {
DefaultRenderer renderer = new DefaultRenderer();
for (int color : colors) {
SimpleSeriesRenderer r = new SimpleSeriesRenderer();
r.setColor(color);
renderer.addSeriesRenderer(r);
}
return renderer;
}
It is possible using achartengine. I have faced the same problem and found the answer now.
Use the 1.1.0-rc2 version of achart engine. You can download it here: http://www.achartengine.org/download/
This tutorial (http://wptrafficanalyzer.in/blog/android-drawing-pie-chart-using-achartengine/) helps you to create pie chart using achartengine.
Add this line to your code to display the %of distribution in the Pie chart
defaultRenderer.setDisplayValues(true);
Reference: How to set different values for Legend and Labels in piechart While I am using Chart Engine in android
Im not sure if you still have this issue. But if your pie chart is fairly simple, you should consider drawing it your self rather using a library for it.
This might help a bit.
https://github.com/blessenm/PieChartDemo

Categories