Are multiple stacked Bar charts possible using Achartengine? - java

I tried adding another set of values to the demo example of stacked bar charts with achartengine, but the new values introduced by me don't appear on the chart. Is Stacking bars limited to two bars?
public Intent getIntent(Context context) {
String[] titles = new String[] { "Good", "Defect", "Repair" };
List<double[]> values = new ArrayList<double[]>();
values.add(new double[] { 14230, 12300, 1424, 15240, 15900, 19200,
22030, 21200, 19500, 15500, 12060, 14000 });
values.add(new double[] { 14230, 12300, 14240, 15244, 15900, 19200,
22030, 21200, 19500, 15500, 12600, 14000 });
values.add(new double[] { 5230, 7300, 9240, 10540, 7900, 9200, 12030,
11200, 9500, 10500, 11600, 13500 });
int[] colors = new int[] { Color.GREEN, Color.YELLOW, Color.RED };
XYMultipleSeriesRenderer renderer = buildBarRenderer(colors);
setChartSettings(renderer, "Machine Efficiency Rates",
"Machine", "NET produce", 0.5, 12.5, 0, 24000, Color.GRAY,
Color.LTGRAY);
renderer.getSeriesRendererAt(0).setDisplayChartValues(true);
renderer.getSeriesRendererAt(1).setDisplayChartValues(true);
renderer.getSeriesRendererAt(2).setDisplayChartValues(true);
renderer.setXLabels(12);
renderer.setYLabels(5);
renderer.setXLabelsAlign(Align.LEFT);
renderer.setYLabelsAlign(Align.LEFT);
renderer.setPanEnabled(true, false);
renderer.setZoomEnabled(true);
renderer.setZoomRate(1.1f);
renderer.setBarSpacing(0.5f);
return ChartFactory.getBarChartIntent(context,
buildBarDataset(titles, values), renderer, Type.STACKED);
}

There is a misunderstanding in the way AChartEngine displays stacked bar charts. It doesn't really stack them, but displays them one over the other. This means that you will want to always add the bigger values first then the smaller and so on as it renders the first series, the second one above the first and so on.
UPDATE: As of version 1.2.0, there is the new HEAP stacked bar charts, which are displayed in the manner you need.

I could not find a good answer. However, you can use the getCombinedXYChartIntent
to create a multiple stacked bars.
I use the CombinedTemperatureChart as a template and modified to achieve this.
The initial raw code is this
package org.achartengine.chartdemo.demo.chart;
import java.util.ArrayList;
import java.util.List;
import org.achartengine.ChartFactory;
import org.achartengine.chart.BarChart;
import org.achartengine.chart.BubbleChart;
import org.achartengine.chart.CubicLineChart;
import org.achartengine.chart.LineChart;
import org.achartengine.chart.PointStyle;
import org.achartengine.model.XYMultipleSeriesDataset;
import org.achartengine.model.XYSeries;
import org.achartengine.model.XYValueSeries;
import org.achartengine.renderer.XYMultipleSeriesRenderer;
import org.achartengine.renderer.XYSeriesRenderer;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.Paint.Align;
/**
* Combined temperature demo chart.
*/
public class CombinedTemperatureChart extends AbstractDemoChart {
/**
* Returns the chart name.
*
* #return the chart name
*/
public String getName() {
return "Combined temperature";
}
/**
* Returns the chart description.
*
* #return the chart description
*/
public String getDesc() {
return "The average temperature in 2 Greek islands, water temperature and sun shine hours (combined chart)";
}
/**
* Executes the chart demo.
*
* #param context the context
* #return the built intent
*/
public Intent execute(Context context) {
String[] titles = new String[] { "Crete Air Temperature", "Skiathos Air Temperature" };
List<double[]> x = new ArrayList<double[]>();
for (int i = 0; i < titles.length; i++) {
x.add(new double[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 });
}
List<double[]> values = new ArrayList<double[]>();
values.add(new double[] { 12.3, 12.5, 13.8, 16.8, 20.4, 24.4, 26.4, 26.1, 23.6, 20.3, 17.2, 13.9 });
values.add(new double[] { 9, 10, 11, 15, 19, 23, 26, 25, 22, 18, 13, 10 });
int[] colors = new int[] { Color.GREEN, Color.rgb(200, 150, 0) };
PointStyle[] styles = new PointStyle[] { PointStyle.CIRCLE, PointStyle.DIAMOND };
XYMultipleSeriesRenderer renderer = buildRenderer(colors, styles);
//renderer.setPointSize(5.5f);
int length = renderer.getSeriesRendererCount();
for (int i = 0; i < length; i++) {
XYSeriesRenderer r = (XYSeriesRenderer) renderer.getSeriesRendererAt(i);
r.setDisplayChartValues(true);
r.setChartValuesTextSize(25);
//r.setLineWidth(2);
r.setFillPoints(true);
}
setChartSettings(renderer, "Weather data", "Month", "Temperature", -1, 12.5, 0, 40,
Color.LTGRAY, Color.LTGRAY);
renderer.setXLabels(12);
renderer.setYLabels(10);
renderer.setShowGrid(true);
renderer.setXLabelsAlign(Align.RIGHT);
renderer.setYLabelsAlign(Align.RIGHT);
renderer.setZoomButtonsVisible(true);
renderer.setPanLimits(new double[] { -10, 20, -10, 40 });
renderer.setZoomLimits(new double[] { -10, 20, -10, 40 });
XYValueSeries sunSeries = new XYValueSeries("Sunshine hours");
sunSeries.add(0.5, 17);
sunSeries.add(1.5, 18);
sunSeries.add(2.5, 19);
sunSeries.add(3.5, 19);
sunSeries.add(4.5, 20.8);
sunSeries.add(5.5, 24.9);
sunSeries.add(6.5, 26);
sunSeries.add(7.5, 27.8);
sunSeries.add(8.5, 28.4);
sunSeries.add(9.5, 25.5);
sunSeries.add(10.5, 23.5);
sunSeries.add(11.5, 19.5);
XYSeriesRenderer lightRenderer = new XYSeriesRenderer();
lightRenderer.setColor(Color.YELLOW);
XYSeries waterSeries = new XYSeries("Water Temperature");
waterSeries.add(0.5, 16);
waterSeries.add(1.5, 15);
waterSeries.add(2.5, 16);
waterSeries.add(3.5, 17);
waterSeries.add(4.5, 20);
waterSeries.add(5.5, 23);
waterSeries.add(6.5, 25);
waterSeries.add(7.5, 25.5);
waterSeries.add(8.5, 26.5);
waterSeries.add(9.5, 24);
waterSeries.add(10.5, 22);
waterSeries.add(11.5, 18);
renderer.setBarSpacing(2);
renderer.setBarWidth(2);
XYSeriesRenderer waterRenderer = new XYSeriesRenderer();
waterRenderer.setColor(Color.argb(250, 0, 210, 250));
XYMultipleSeriesDataset dataset = buildDataset(titles, x, values);
dataset.addSeries(0, sunSeries);
dataset.addSeries(1, waterSeries);
renderer.setBarWidth(0.5f);
renderer.addSeriesRenderer(lightRenderer);
renderer.addSeriesRenderer(waterRenderer);
waterRenderer.setDisplayChartValues(true);
waterRenderer.setChartValuesTextSize(25);
lightRenderer.setDisplayChartValues(true);
lightRenderer.setChartValuesTextSize(25);
String[] types = new String[] { BarChart.TYPE, BarChart.TYPE, BarChart.TYPE, BarChart.TYPE };
Intent intent = ChartFactory.getCombinedXYChartIntent(context, dataset, renderer, types,
"Weather parameters");
return intent;
}
}
I hope someone still need this, it take a some time figure it out.
Unfortunately, I don't have the points to paste an image.

Related

How to create a surface chart with Apache POI?

Does anyone know how to create a surface chart with Apache POI?
Unfortunately I could not find an example anywhere.
I tried to use other chart examples but without success.
Since XDDF was introduced with apache poi 4, this should be used. And XDDFChartData has a subclass XDDFSurface3DChartData.
What one needs to know when using:
A surface 3D chart needs an additional series axis. And this series axis needs to be defined for the XDDFSurface3DChartData.
Minimal example which creates a Excel sheet having a surface 3D chart. This is tested and works using the current apache poi 5.2.2.
import java.io.FileOutputStream;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xddf.usermodel.*;
import org.apache.poi.xddf.usermodel.chart.*;
import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
import org.apache.poi.xssf.usermodel.XSSFDrawing;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
public class CreateExcelXDDFSurface3DChart {
public static void main(String[] args) throws Exception {
try (XSSFWorkbook document = new XSSFWorkbook()) {
XSSFSheet sheet = document.createSheet("SurfaceChart");
// create the data
String[] categories = new String[] { "c1", "c2", "c3", "c4", "c5", "c6", "c7", "c8", "c9" };
Double[] values1 = new Double[] { 10d, 20d, 10d, 15d, 12d, 20d, 10d, 18d, 19d };
Double[] values2 = new Double[] { 20d, 10d, 15d, 20d, 11d, 17d, 18d, 20d, 10d };
Double[] values3 = new Double[] { 14.5d, 14d, 13.5d, 13d, 12.5d, 12d, 11.5d, 11d, 10.5d };
int r = 0;
for (String cat : categories) {
sheet.createRow(r).createCell(0).setCellValue(cat);
sheet.getRow(r).createCell(1).setCellValue(values1[r]);
sheet.getRow(r).createCell(2).setCellValue(values2[r]);
sheet.getRow(r).createCell(3).setCellValue(values3[r]);
r++;
}
// create the chart
XSSFDrawing drawing = sheet.createDrawingPatriarch();
XSSFClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, 5, 0, 20, 30);
XDDFChart chart = drawing.createChart(anchor);
// create data sources
int numOfPoints = categories.length;
XDDFDataSource<String> categoriesData = XDDFDataSourcesFactory.fromStringCellRange(sheet, new CellRangeAddress(0, numOfPoints-1, 0, 0));
XDDFNumericalDataSource<Double> valuesData1 = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(0, numOfPoints-1, 1, 1));
XDDFNumericalDataSource<Double> valuesData2 = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(0, numOfPoints-1, 2, 2));
XDDFNumericalDataSource<Double> valuesData3 = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(0, numOfPoints-1, 3, 3));
// surface 3D chart
XDDFCategoryAxis categoryAxis = chart.createCategoryAxis(AxisPosition.BOTTOM);
XDDFValueAxis valueAxis = chart.createValueAxis(AxisPosition.LEFT);
valueAxis.setCrosses(AxisCrosses.AUTO_ZERO);
// surface 3D chart needs a series axis
XDDFSeriesAxis seriesAxis = chart.createSeriesAxis(AxisPosition.BOTTOM);
seriesAxis.setCrosses(AxisCrosses.AUTO_ZERO);
seriesAxis.crossAxis(valueAxis);
XDDFChartData data = chart.createData(ChartTypes.SURFACE3D, categoryAxis, valueAxis);
// surface 3D chart needs the series axis applied to the XDDFSurface3DChartData
((XDDFSurface3DChartData)data).defineSeriesAxis(seriesAxis);
XDDFChartData.Series series = data.addSeries(categoriesData, valuesData1);
series.setTitle("Series 1", null);
series = data.addSeries(categoriesData, valuesData2);
series.setTitle("Series 2", null);
series = data.addSeries(categoriesData, valuesData3);
series.setTitle("Series 3", null);
chart.plot(data);
// set legend
XDDFChartLegend legend = chart.getOrAddLegend();
legend.setPosition(LegendPosition.BOTTOM);
// Write the output to a file
try (FileOutputStream fileOut = new FileOutputStream("./CreateExcelXDDFSurface3DChart.xlsx")) {
document.write(fileOut);
}
}
}
}
Btw.: I have never understood where a surface chart will be helpful for data presentation.

How to use SharedPreferences in Achartengine line graph?

I want to use SharedPreferences in the code for LineGraph:
public class LineGraph{
Context applicationContext;
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(applicationContext);
public Intent getIntent(Context context) {
// Our first data
int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; // x values!
int[] y = { 30, 34, 45, 57, 77, 89, 100, 111 ,123 ,145 }; // y values!
TimeSeries series = new TimeSeries("Line1");
for( int i = 0; i < x.length; i++)
{
series.add(x[i], y[i]);
}
// Our second data
int[] x2 = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; // x values!
int[] y2 = { 145, 123, 111, 100, 89, 77, 57, 45, 34, 30}; // y values!
TimeSeries series2 = new TimeSeries("Line2");
for( int i = 0; i < x2.length; i++)
{
series2.add(x2[i], y2[i]);
}
XYMultipleSeriesDataset dataset = new XYMultipleSeriesDataset();
dataset.addSeries(series);
dataset.addSeries(series2);
XYMultipleSeriesRenderer mRenderer = new XYMultipleSeriesRenderer(); // Holds a collection of XYSeriesRenderer and customizes the graph
mRenderer.setZoomButtonsVisible(true);
XYSeriesRenderer renderer = new XYSeriesRenderer(); // This will be used to customize line 1
XYSeriesRenderer renderer2 = new XYSeriesRenderer(); // This will be used to customize line 2
mRenderer.addSeriesRenderer(renderer);
mRenderer.addSeriesRenderer(renderer2);
// Customization time for line 1!
renderer.setColor(Color.WHITE);
renderer.setPointStyle(PointStyle.SQUARE);
renderer.setFillPoints(true);
// Customization time for line 2!
renderer2.setColor(Color.YELLOW);
renderer2.setPointStyle(PointStyle.DIAMOND);
renderer2.setFillPoints(true);
Intent intent = ChartFactory.getLineChartIntent(context, dataset, mRenderer, "Line Graph Title");
return intent;
}
}
But the SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(applicationContext);
does not work, it stopped the application. Why?
Call this within your method, not at the class level.
Something like this:
public class LineGraph {
public Intent getIntent(Context context) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
// Our first data
int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; // x values!
...
The way you had it, applicationContext was always going to be null.
Please provide your logcat-output.
Apart from this I assume that you receive a nullpointer exception when itializing the shared preferences, because the applicationContext-variable is null.
Place the initialization of your shared preferences into the getIntent()-method and pass the context-argument.

Load arrayList data into JTable

I'm trying to set items from a method called FootballClub and so far it's fine.
but then I created an arrayList from it and I somehow can't find a way to store this information into a JTable.
The problem is that i cant find a way to set a fixed number of rows
Here is my code:
Class StartLeague:
import javax.swing.*;
import javax.swing.table.*;
import java.awt.*;
public class startLeague implements LeagueManager{
//setting the frame and other components to appear
public startLeague(){
JButton createTeam = new JButton("Create Team");
JButton deleteTeam = new JButton("Delete Team");
JFrame frame = new JFrame("Premier League System");
JPanel panel = new JPanel();
frame.setSize(1280, 800);
frame.setVisible(true);
frame.add(panel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
String col[] = {"Pos","Team","P", "W", "L", "D", "MP", "GF", "GA", "GD"};
panel.setLayout(new GridLayout(20, 20));
panel.add(createTeam);
panel.add(deleteTeam);
panel.add(new JLabel(""));
//JLabels to fill the space
}
}
FootBall Club Class:
import java.util.ArrayList;
public class FootballClub extends SportsClub{
FootballClub(int position, String name, int points, int wins, int defeats, int draws, int totalMatches, int goalF, int goalA, int goalD){
this.position = position;
this.name = name;
this.points = points;
this.wins = wins;
this.defeats = defeats;
this.draws = draws;
this.totalMatches = totalMatches;
this.goalF = goalF;
this.goalA = goalA;
this.goalD = goalD;
}
The SportsClub Class(abstract):
abstract class SportsClub {
int position;
String name;
int points;
int wins;
int defeats;
int draws;
int totalMatches;
int goalF;
int goalA;
int goalD;
}
And finally, LeagueManager, which is an interface:
import java.util.ArrayList;
public interface LeagueManager {
ArrayList<FootballClub> originalLeagueTable = new ArrayList<FootballClub>();
FootballClub arsenal = new FootballClub(1, "Arsenal", 35, 11, 2, 2, 15, 30, 11, 19);
FootballClub liverpool = new FootballClub(2, "Liverpool", 30, 9, 3, 3, 15, 34, 18, 16);
FootballClub chelsea = new FootballClub(3, "Chelsea", 30, 9, 2, 2, 15, 30, 11, 19);
FootballClub mCity = new FootballClub(4, "Man City", 29, 9, 2, 4, 15, 41, 15, 26);
FootballClub everton = new FootballClub(5, "Everton", 28, 7, 1, 7, 15, 23, 14, 9);
FootballClub tot = new FootballClub(6, "Tottenham", 27, 8, 4, 3, 15, 15, 16, -1);
FootballClub newcastle = new FootballClub(7, "Newcastle", 26, 8, 5, 2, 15, 20, 21, -1);
FootballClub south = new FootballClub(8, "Southampton", 23, 6, 4, 5, 15, 19, 14, 5);
}
Can somebody please help me?
I've trying and trying for days.
Thank you.
"The problem is that i cant find a way to set a fixed number of rows"
You don't need to set the number of rows. Use a TableModel. A DefaultTableModel in particular.
String col[] = {"Pos","Team","P", "W", "L", "D", "MP", "GF", "GA", "GD"};
DefaultTableModel tableModel = new DefaultTableModel(col, 0);
// The 0 argument is number rows.
JTable table = new JTable(tableModel);
Then you can add rows to the tableModel with an Object[]
Object[] objs = {1, "Arsenal", 35, 11, 2, 2, 15, 30, 11, 19};
tableModel.addRow(objs);
You can loop to add your Object[] arrays.
Note: JTable does not currently allow instantiation with the input data as an ArrayList. It must be a Vector or an array.
See JTable and DefaultTableModel. Also, How to Use JTable tutorial
"I created an arrayList from it and I somehow can't find a way to store this information into a JTable."
You can do something like this to add the data
ArrayList<FootballClub> originalLeagueList = new ArrayList<FootballClub>();
originalLeagueList.add(new FootballClub(1, "Arsenal", 35, 11, 2, 2, 15, 30, 11, 19));
originalLeagueList.add(new FootballClub(2, "Liverpool", 30, 9, 3, 3, 15, 34, 18, 16));
originalLeagueList.add(new FootballClub(3, "Chelsea", 30, 9, 2, 2, 15, 30, 11, 19));
originalLeagueList.add(new FootballClub(4, "Man City", 29, 9, 2, 4, 15, 41, 15, 26));
originalLeagueList.add(new FootballClub(5, "Everton", 28, 7, 1, 7, 15, 23, 14, 9));
originalLeagueList.add(new FootballClub(6, "Tottenham", 27, 8, 4, 3, 15, 15, 16, -1));
originalLeagueList.add(new FootballClub(7, "Newcastle", 26, 8, 5, 2, 15, 20, 21, -1));
originalLeagueList.add(new FootballClub(8, "Southampton", 23, 6, 4, 5, 15, 19, 14, 5));
for (int i = 0; i < originalLeagueList.size(); i++){
int position = originalLeagueList.get(i).getPosition();
String name = originalLeagueList.get(i).getName();
int points = originalLeagueList.get(i).getPoinst();
int wins = originalLeagueList.get(i).getWins();
int defeats = originalLeagueList.get(i).getDefeats();
int draws = originalLeagueList.get(i).getDraws();
int totalMatches = originalLeagueList.get(i).getTotalMathces();
int goalF = originalLeagueList.get(i).getGoalF();
int goalA = originalLeagueList.get(i).getGoalA();
in ttgoalD = originalLeagueList.get(i).getTtgoalD();
Object[] data = {position, name, points, wins, defeats, draws,
totalMatches, goalF, goalA, ttgoalD};
tableModel.add(data);
}
You probably need to use a TableModel (Oracle's tutorial here)
How implements your own TableModel
public class FootballClubTableModel extends AbstractTableModel {
private List<FootballClub> clubs ;
private String[] columns ;
public FootBallClubTableModel(List<FootballClub> aClubList){
super();
clubs = aClubList ;
columns = new String[]{"Pos","Team","P", "W", "L", "D", "MP", "GF", "GA", "GD"};
}
// Number of column of your table
public int getColumnCount() {
return columns.length ;
}
// Number of row of your table
public int getRowsCount() {
return clubs.size();
}
// The object to render in a cell
public Object getValueAt(int row, int col) {
FootballClub club = clubs.get(row);
switch(col) {
case 0: return club.getPosition();
// to complete here...
default: return null;
}
}
// Optional, the name of your column
public String getColumnName(int col) {
return columns[col] ;
}
}
You maybe need to override anothers methods of TableModel, depends on what you want to do, but here is the essential methods to understand and implements :)
Use it like this
List<FootballClub> clubs = getFootballClub();
TableModel model = new FootballClubTableModel(clubs);
JTable table = new JTable(model);
Hope it help !
I created an arrayList from it and I somehow can't find a way to store this information into a JTable.
The DefaultTableModel doesn't support displaying custom Objects stored in an ArrayList. You need to create a custom TableModel.
You can check out the Bean Table Model. It is a reusable class that will use reflection to find all the data in your FootballClub class and display in a JTable.
Or, you can extend the Row Table Model found in the above link to make is easier to create your own custom TableModel by implementing a few methods. The JButtomTableModel.java source code give a complete example of how you can do this.
You can do something like what i did with my List< Future< String > > or any other Arraylist, Type returned from other class called PingScan that returns List> because it implements service executor. Anyway the code down note that you can use foreach and retrieve data from the List.
PingScan p = new PingScan();
List<Future<String>> scanResult = p.checkThisIP(jFormattedTextField1.getText(), jFormattedTextField2.getText());
for (final Future<String> f : scanResult) {
try {
if (f.get() instanceof String) {
String ip = f.get();
Object[] data = {ip};
tableModel.addRow(data);
}
} catch (InterruptedException | ExecutionException ex) {
Logger.getLogger(gui.class.getName()).log(Level.SEVERE, null, ex);
}
}
Basic method for beginners like me.
public void loadDataToJtable(ArrayList<String> liste){
rows = table.getRowCount();
cols = table.getColumnCount();
for (int i = 0; i < rows ; i++) {
for ( int k = 0; k < cols ; k++) {
for (int h = 0; h < list1.size(); h++) {
String b = list1.get(h);
b = table.getValueAt(i, k).toString();
}
}
}
}

AcharEngine making Date related graph

I am trying to make a plot of weight of an animal stored with soem specific date. I have Weight Class with two vars , Date and Weight.
Here is the code I am using.
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"));
}
The problem with this code is, it never shows anything on x Axis and no graph line is also displayed.
Secondly, What If I want to show data from specific date to another date? Like from Feb to March etc.?
I have used your code to build an example to compile and run for me. Please see the code below that displays a chart correctly. The code builds an Intent, so you will have to change the last line to build a View.
So, if you are really sure that you really put data into the model than you should check the layout. You are probably not adding the chart view to your layout correctly.
List<Date> wtArray = new ArrayList<Date>();
double[] weight = new double[] { 70, 71, 74, 73, 70, 71, 75, 76, 75, 73, 75, 73 };
for (int i = 0; i < 12; i++) {
wtArray.add(new Date(108, i, 1));
}
TimeSeries diaSeries = new TimeSeries("Weight");
for (int i = 0; i < wtArray.size(); i++) {
diaSeries.add(wtArray.get(i), weight[i]);
}
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);
return ChartFactory.getTimeChartIntent(context, dataset, mrenderer, "MM/dd/yyyy");

What are tiles and how are they created in the BufferedImage

I posted a question in sun java forums sometime ago and i am finding it hard to understand the first response i received from the replier though it seems he gave me the correct approach to my problem. The link to the question is:
http://forums.sun.com/thread.jspa?threadID=5436562&tstart=0
Someone replied that i should use BufferedImage and make tiles. I don't really understand what the tiles mean in connection with the BufferedImage.
I would like someone to explain to me what the tiles are and how they are created in the BufferedImage.
I have searched the web for a while but couldn't find any link that can help me understanding the basics of the tiles and creating the tiles. Any pointer to a site is also appreciated.
I need help in understanding the tiles in connection with the BufferedImage and also how they are created.
A "tile" in a 2D game simply means an "image smaller than whole screen that you can reuse several times to create the background".
Here's a a working example where four tiles are created (adding some random noise to every pixel). Each tile is 50x50 pixels.
Then there's a "map" (that you call a "grid" in your case) representing which tiles you want to put where.
From that map, a bigger BufferedImage is created (note that it's just an example, in a real program you'll want to use a BufferedImage copy, not a pixel-by-pixel copy).
The map is 9x7, each tile is 50x50 pixels, hence the resulting image is 9*50 x 7*50 (ie 450 by 350).
Note that the following is really just a simple example, as short as possible, showing how to create a bigger BufferedImage using several tiles: the goal is not to give a tutorial on best Swing usage nor on how to squeeze every bit of performances out of BufferedImages, etc.
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.Random;
public class ToyTiled extends JFrame {
private static final int IMAGE_TYPE = BufferedImage.TYPE_INT_ARGB;
private BufferedImage img;
public static void main( String[] args ) {
new ToyTiled();
}
public ToyTiled() {
super();
this.add(new JPanel() {
#Override
protected void paintComponent(Graphics g) {
g.drawImage(img, 0, 0, null);
}
});
img = new BufferedImage( 450, 350, IMAGE_TYPE ); // here you should create a compatible BufferedImage
this.setSize(img.getWidth(), img.getHeight());
this.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
final int NB_TILES = 4;
BufferedImage[] tiles = new BufferedImage[NB_TILES];
tiles[0] = createOneTile( new Color( 255, 255, 255 ) );
tiles[1] = createOneTile( new Color( 255, 0, 255 ) );
tiles[2] = createOneTile( new Color( 0, 0, 255 ) );
tiles[3] = createOneTile( new Color( 0, 255, 255 ) );
final int[][] map = new int[][] {
{ 1, 0, 2, 3, 0, 1, 2, 2, 2 },
{ 0, 2, 3, 0, 1, 2, 2, 2, 3 },
{ 1, 0, 2, 3, 0, 1, 2, 2, 2 },
{ 2, 1, 0, 1, 2, 3, 2, 0, 0 },
{ 1, 0, 2, 3, 0, 1, 2, 2, 3 },
{ 1, 0, 2, 2, 1, 1, 2, 2, 3 },
{ 1, 0, 2, 3, 0, 1, 2, 2, 3 },
};
for (int i = 0; i < map[0].length; i++) {
for (int j = 0; j < map.length; j++) {
final BufferedImage tile = tiles[map[j][i]];
for (int x = 0; x < tile.getWidth(); x++) {
for (int y = 0; y < tile.getHeight(); y++) {
img.setRGB( x + i * 50, y + j * 50, tile.getRGB(x,y) );
}
}
}
}
this.setVisible( true );
}
private BufferedImage createOneTile( final Color c ) {
final Random r = new Random();
final BufferedImage res = new BufferedImage( 50, 50, IMAGE_TYPE );
for (int x = 0; x < res.getWidth(); x++) {
for (int y = 0; y < res.getHeight(); y++) {
res.setRGB( x, y, c.getRGB() - r.nextInt(150) );
}
}
return res;
}
}
If you want to rotate a portion of a BufferedImage you might find these classes/methods useful:
AffineTransform.getRotateInstance or AffineTransform.getQuadrantRotateInstance
AffineTransformOp
BufferedImage.getSubImage()
BufferedImage.setData
Example:
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.awt.image.BufferedImageOp;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.AbstractAction;
import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.WindowConstants;
public class TileTest extends JFrame {
public static void main(String[] args) throws IOException {
URL logo = new URL("http://sstatic.net/so/img/logo.png");
TileTest tileTest = new TileTest(ImageIO.read(logo));
tileTest.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
tileTest.setVisible(true);
}
private TileTest(BufferedImage image) throws IOException {
this.image = image;
setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS));
JLabel label = new JLabel(new ImageIcon(image));
add(label);
BufferedImage tile = image.getSubimage(0, 0, 61, 61);
add(new JButton(new RotateAction(tile, label)));
pack();
}
private BufferedImage image;
}
class RotateAction extends AbstractAction {
public void actionPerformed(ActionEvent e) {
BufferedImage tmpImage = op.filter(image, null);
image.setData(tmpImage.getRaster());
component.repaint();
}
RotateAction(BufferedImage image, Component component) {
super("Rotate");
this.component = component;
this.image = image;
double x = 0.5 * image.getWidth();
double y = 0.5 * image.getHeight();
AffineTransform xfrm =
AffineTransform.getQuadrantRotateInstance(1, x, y);
op = new AffineTransformOp(
xfrm, AffineTransformOp.TYPE_NEAREST_NEIGHBOR);
}
private final Component component;
private final BufferedImage image;
private final BufferedImageOp op;
}

Categories