问题
I have created a graph where tamperatures are displayed in a timeChart. I needed to mark a few temperatures with different color, so I used a XYCombinedChart and added a ScatterChar with the temperatures I wanted to mark. It all worked well. The only problem is that, in order to make it work, I used milliseconds in ScatterCharts's XYSeries like shown below:
XYSeries pointSeries = new XYSeries("NotFromSensor");
dataset.addSeries(pointSeries);
int t = 0;
for (t = 0; t < MainActivity.temps.size(); t++){
pointSeries.add(dt[t].getTime(), MainActivity.temps.get(t));
}
The whole code of creating the graph is shown below:
public class DeviceGraphActivity extends Activity {
private XYMultipleSeriesDataset dataset, pointDataset ;
private XYMultipleSeriesRenderer mRenderer;
private XYSeriesRenderer renderer1, pointRenderer;
public GraphicalView getDeviceView(Context context, String title){
dataset = new XYMultipleSeriesDataset();
clearDataset();// a set with all the data that will be displayed on the graph
mRenderer = new XYMultipleSeriesRenderer();//determines the variables of the overall graph
int i;
System.out.println(ShowGraphActivity.flag);
if(DeviceFilterActivity.checkedDevices.isEmpty()){
if(ShowGraphActivity.flag == true){
MainActivity.setXYValues("SELECT Temperature, Time FROM Temperatures WHERE Time BETWEEN " +
"'"+(MainActivity.yy1)+"-"+((MainActivity.mm1))+"-"+(MainActivity.dd1)+"' " +
"AND '"+(MainActivity.yy2)+"-"+((MainActivity.mm2))+"-"+((MainActivity.dd2))+"'");
setData(false);
MainActivity.setXYValues("SELECT Temperature, Time FROM Temperatures WHERE FromSensor = 0 AND Time BETWEEN " +
"'"+(MainActivity.yy1)+"-"+((MainActivity.mm1))+"-"+(MainActivity.dd1)+"' " +
"AND '"+(MainActivity.yy2)+"-"+((MainActivity.mm2))+"-"+((MainActivity.dd2))+"'");
setData(true);
}
else{
MainActivity.setXYValues("SELECT Temperature, Time FROM Temperatures");
setData(false);
MainActivity.setXYValues("SELECT Temperature, Time FROM Temperatures WHERE FromSensor = 0");
setData(true);
}
renderer1 = new XYSeriesRenderer();
renderer1.setLineWidth(3);//sets graph line's width
renderer1.setChartValuesTextSize(20);//sets the size of the text on the char
renderer1.setColor(Color.BLUE);//sets the color of the graph
renderer1.setDisplayBoundingPoints(true);
mRenderer.addSeriesRenderer(renderer1);//adds the renderer(1 graph) to the overall graph
pointRenderer = new XYSeriesRenderer();
pointRenderer.setLineWidth(3);//sets graph line's width
pointRenderer.setChartValuesTextSize(20);//sets the size of the text on the char
pointRenderer.setPointStyle(PointStyle.CIRCLE);
pointRenderer.setColor(Color.RED);//sets the color of the graph
pointRenderer.setDisplayBoundingPoints(true);
mRenderer.addSeriesRenderer(pointRenderer);
}
else{
for(i = 0; i < DeviceFilterActivity.checkedDevices.size(); i++){
if(ShowGraphActivity.flag){
MainActivity.setXYValues("SELECT Temperature, Time FROM Temperatures WHERE DeviceID = "+DeviceFilterActivity.checkedDevices.get(i).getId()+" AND Time BETWEEN " +
"'"+(MainActivity.yy1)+"-"+((MainActivity.mm1))+"-"+(MainActivity.dd1)+"' " +
"AND '"+(MainActivity.yy2)+"-"+((MainActivity.mm2))+"-"+((MainActivity.dd2))+"'");
setData(i, false);
MainActivity.setXYValues("SELECT Temperature, Time FROM Temperatures WHERE FromSensor = 0 AND DeviceID = "+DeviceFilterActivity.checkedDevices.get(i).getId()+" AND Time BETWEEN " +
"'"+(MainActivity.yy1)+"-"+((MainActivity.mm1))+"-"+(MainActivity.dd1)+"' " +
"AND '"+(MainActivity.yy2)+"-"+((MainActivity.mm2))+"-"+((MainActivity.dd2))+"'");
setData(i,true);
}
else{
MainActivity.setXYValues("SELECT Temperature, Time FROM Temperatures WHERE DeviceID = "+DeviceFilterActivity.checkedDevices.get(i).getId());
setData(i, false);
MainActivity.setXYValues("SELECT Temperature, Time FROM Temperatures WHERE FromSensor = 0 AND DeviceID = "+DeviceFilterActivity.checkedDevices.get(i).getId());
setData(i, true);
}
renderer1 = new XYSeriesRenderer();
renderer1.setLineWidth(3);//sets graph line's width
renderer1.setChartValuesTextSize(20);//sets the size of the text on the chart
renderer1.setColor(DeviceFilterActivity.checkedColors.get(i));//sets the color of the graph
renderer1.setDisplayBoundingPoints(true);
mRenderer.addSeriesRenderer(renderer1);//adds the renderer(1 graph) to the overall graph
pointRenderer = new XYSeriesRenderer();
pointRenderer.setLineWidth(3);//sets graph line's width
pointRenderer.setChartValuesTextSize(20);//sets the size of the text on the chart
pointRenderer.setColor(Color.RED);//sets the color of the graph
pointRenderer.setDisplayBoundingPoints(true);
mRenderer.addSeriesRenderer(pointRenderer);
}
}
mRenderer.setLabelsTextSize(20);
mRenderer.setPanEnabled(true);
mRenderer.setZoomEnabled(true);
mRenderer.setZoomButtonsVisible(true);
mRenderer.setYAxisMax(50);
mRenderer.setYAxisMin(0);
mRenderer.setShowGrid(true);
mRenderer.setMargins(new int[] { 50, 50, 25, 22 });
mRenderer.setLegendTextSize(25);
// we show the grid
mRenderer.setInScroll(true);
mRenderer.setChartTitle(title);
mRenderer.setChartTitleTextSize(30);
//------------------------
mRenderer.setClickEnabled(false);//the graph can't be clicked so that it can be refreshed as well as be zoomed in or out
mRenderer.setSelectableBuffer(10);
//---------------------------
String[] types = new String[]{ new String(TimeChart.TYPE), new String(ScatterChart.TYPE)};
//return ChartFactory.getTimeChartView(context, dataset, mRenderer, "YYYY-MM-DD");
return ChartFactory.getCombinedXYChartView(context, dataset, mRenderer, types);//return a graph depending on the above declarations, that will be used as a view in the previous activity
}
public void setData(boolean arePoints){//sets the temperatures and dates data that will be used on the graph
Date[] dt = new Date[MainActivity.dates.size()];
for (int k = 0; k< MainActivity.dates.size(); k++){
GregorianCalendar gc = new GregorianCalendar(MainActivity.dates.get(k).getYy(),
MainActivity.dates.get(k).getMM()-1,MainActivity.dates.get(k).getDd(),
MainActivity.dates.get(k).getHh(),MainActivity.dates.get(k).getMm(),
MainActivity.dates.get(k).getSs());
dt[k] = gc.getTime();
}
if(!arePoints){
TimeSeries series = new TimeSeries("Temperature");
dataset.addSeries(series);
int t = 0;
for (t = 0; t < MainActivity.temps.size(); t++){
series.add(dt[t] , MainActivity.temps.get(t));
}
}
else{
XYSeries pointSeries = new XYSeries("NotFromSensor");
dataset.addSeries(pointSeries);
int t = 0;
for (t = 0; t < MainActivity.temps.size(); t++){
pointSeries.add(dt[t].getTime(), MainActivity.temps.get(t));
}
}
}
public void setData(int i,boolean arePoints){//sets the temperatures and dates data that will be used on the graph
Date[] dt = new Date[MainActivity.dates.size()];
for (int k = 0; k< MainActivity.dates.size(); k++){
GregorianCalendar gc = new GregorianCalendar(MainActivity.dates.get(k).getYy(),
MainActivity.dates.get(k).getMM()-1,MainActivity.dates.get(k).getDd(),
MainActivity.dates.get(k).getHh(),MainActivity.dates.get(k).getMm(),
MainActivity.dates.get(k).getSs());
dt[k] = gc.getTime();
}
if(!arePoints){
TimeSeries series = new TimeSeries("device "+DeviceFilterActivity.checkedDevices.get(i).getName());
dataset.addSeries(series);
int t = 0;
for (t = 0; t < MainActivity.temps.size(); t++){
series.add(dt[t] , MainActivity.temps.get(t));
}
}
else{
XYSeries pointSeries = new XYSeries("NotFromSensor");
dataset.addSeries(pointSeries);
int t = 0;
for (t = 0; t < MainActivity.temps.size(); t++){
pointSeries.add(dt[t].getTime() , MainActivity.temps.get(t));
}
}
}
public void clearDataset(){
this.dataset.clear();
}
}
Obviously the chart shows the time in milliseconds. How can I use the X-Axis from the TimeChart and show the real dates?
回答1:
I just found a solution to this problem. It's a custom library, something like an extention to the original AChartEngine. It includes a class named CombinedTimeChart. It is the exact same as the CombinedXYChart, but you can set the x-axis with the proper dates, without having to manually set its labels. I provide a link to get the library:
https://github.com/hdodenhof/achartengine
Credits to the creator for his good work. I tested it and works just great. The only thing you have to do is import the whole project into your workspace (if using Eclipse) and the import it as a library into your project:
- right click on your project name in Package Explorer.
- Properties
- Android
- Add...
- Choose the folder with the name of the imported project (achartengine-master)
- Apply
- OK
Now you are ready to use the library as you would have normally done with the original AChartEngine library. Remember to use the method ChartFactory.getCombinedTimeChartView(context, dataset, renderer, type)
to get the chart with the choosen graphs.
I have seen many related questions around the forum with the answer "use CombinedXYChart with a LineChart and a ScatterChart", which is not a bad solution, but in my opinion the above is a better and easier way to create this kind of chart.
Hope it helps.
来源:https://stackoverflow.com/questions/27484327/achartengine-combined-timechart-and-scatterchart-x-axis-date