O gráfico do Caelum Mock
Por Guilherme de Almeida Moreira em 29/01/07Eu gostaria de começar esse post já comentando de como eu criei o gráfico, mas eu recomendo aos leitores que visitem a página Caelumock, façam um teste e vejam o gráfico de aproveitamento no final dele, pois é sobre ele que escreverei a partir de agora.
Em geral no JFreechart temos que seguir alguns passos para montar um gráfico, o primeiro deles é definir qual o tipo de gráfico que desejamos montar, pois a partir dessa escolha é que vamos montar o conjunto de dados, o Dataset.
Como conferimos no site, o tipo do gráfico escolhido foi um do tipo de barras. Um gráfico com barras requer um Dataset do tipo categoria.
DefaultCategoryDataset dataset = new DefaultCategoryDataset();
Este tipo de Dataset permite ao usuário definir vários conjuntos, que iriam gerar várias barras com cores diferentes para cada conjunto. No exemplo atual vamos utilizar apenas um conjunto, o de “Acertos (%)”.
O primeiro dado que inseriremos no gráfico é a porcentagem geral de acertos, repare que além do valor e do conjunto, também temos que avisar qual o nome daquela barra, ou seja primeiro parâmetro é o valor, o segundo é o conjunto e o terceiro é o nome da barra, o segundo e o terceiro devem ser Comparable’s pois o Jfreechart vai comparar os grupos para organizar a ordem e as cores das barras e vai comparar os nomes das barras para poder juntar as que tiverem o mesmo nome.
dataset.addValue(mockStatistics.getPercentageOfTotal(), "Acertos (%)", "Geral");
Agora os próximos dados são as taxas de acerto por categoria. Os dados pertencem à outra classe, que não está em questão, mas o nome já é auto-explicativo.
for (int i = 0; i < mockStatistics.getListOfCategories().size(); i++) {
dataset.addValue(mockStatistics.getPercentageByCategory(i),
"Acertos (%)", mockStatistics.getListOfCategories().get(i).getId().getName());
}
Já temos os dados mas ainda falta criar o gráfico. O JFreechart disponibiliza uma classe (abstrata) que cria os gráficos, ela se chama ChartFactory (nada sugestivo hein
) e contém métodos estáticos que devolvem objetos do tipo JFreechart.
No caso do gráfico em barras temos que passar 8 (oito) parâmtros:
1º - String - título (pode ser null)
2º - String - nome que vão aparecer nas categorias (pode ser null)
3º - String - nome que vai aparecer ao lado dos dados (pode ser null)
4º - CategoryDataset - Dataset que criamos
5º - PlotOrientation - indica se o gráfico vai ser na horizontal ou vertical (o JFreechart já tem uma ajudinha pronta pra isso)
6º - boolean - mostrar ou não legendas
7º - boolean - gerar ou não tooltips
8º - boolean/code> - gerar ou não url's
Assim, na pŕoxima instrução vamos usar o ChartFactory (abstrata) para criar um gráfico de Barra 3D, definindo o título como "Sua Pontuação", o nome das categorias não precisa de nada, o nome dos dados como "Pontos (%)", utilizando o Dataset criado anteriormente, passando a constante HORIZONTAL da classe PlotOrientation para avisar que o gráfico é na horizontal, mostrando as legendas e ignorando tooltip e as URL’s.
JFreeChart chart = ChartFactory.createBarChart3D("Sua Pontuação",
null, "Pontos (%)", dataset, PlotOrientation.HORIZONTAL,
true, false, false);
Finalizando, temos que colocar o gráfico no response da Servlet (no site uso o VRaptor assim eu tenho uma lógica que não devolve view nenhuma, apenas um response do tipo “image/png”).
Primeiro mudamos o tipo de do conteúdo do response para image/png
response.setContentType("image/png");
Com o objeto response, pegamos o seu OutputStream e atribuimos a uma nova variável que será usada na hora de renderizar o gráfico.
OutputStream os = response.getOutputStream();
O JFreechart também disponibiliza algumas ferramentas que auxiliam os programadores a renderizar os gráficos de várias maneiras, como, renderizar direto para um arquivo, para um outputstream ou mesmo no formato JPEG ou PNG, definir qualidade e etc..
ChartUtilities.writeChartAsPNG(os, chart, 500, 300);
Depois é só fechar o Outputstream e fim!
os.close();
Além do apresentado ainda podemos utilizar algumas opções um pouco mais avançadas, como mudar o range dos números (como o gráfico representa valores em porcentagem, o mais correto a se fazer é deixar o limite dos números entre 0 à 100), mudar a cor das barras:
Para ambas modificações temos que que pegar o CategoryPlot do gráfico:
CategoryPlot plot = chart.getCategoryPlot();
Mudar o range(limite) para números de 0 à 100:
plot.getRangeAxis().setRange(0, 100);
Mudar as cores das barras é um pouco mais complicado, mas não se assustem esse pouco mais complicado é bem pouco, do objeto plot você deve pegar o Renderer, mas ele vai devolver um CategoryItemRender, então você deve fazer um cast para o tipo BarRender. Depois o método a ser chamado no renderer é o setSeriesPaint, que vai pintar uma série escolhida, que no caso é a primeira (índice 0) e da cor escolhida.
BarRenderer renderer = (BarRenderer)plot.getRenderer();
renderer.setSeriesPaint(0, Color.BLUE);
Outra coisa que ainda podemos mudar é a altura do gráfico dinâmicamente, pois a altura vai depender de quantas categorias a prova teve. Assim podemos especificar uma altura mínima, e somar com uma altura multiplicada por quantas categorias a prova teve:
int height = dataset.getColumnCount()*45 + 65;
ChartUtilities.writeChartAsPNG(os, chart, 500, height);
Obs: Os valores da altura foram obtidos através de testes!

Veja o código completo:
@Viewless
public void render() {
DefaultCategoryDataset dataset = new DefaultCategoryDataset();
dataset.addValue(mockStatistics.getPercentageOfTotal(),
"Acertos (%)", "Geral");
for (int i = 0; i < mockStatistics.getListOfCategories().size(); i++) {
dataset.addValue(mockStatistics.getPercentageByCategory(i),
"Acertos (%)", mockStatistics
.getListOfCategories().get(i).getId().getName());
}
JFreeChart chart = ChartFactory.createBarChart3D("Sua Pontuação",
"", "Pontos (%)", dataset, PlotOrientation.HORIZONTAL, true, false,
false);
CategoryPlot plot = chart.getCategoryPlot();
plot.getRangeAxis().setRange(0, 100);
BarRenderer renderer = (BarRenderer)plot.getRenderer();
renderer.setSeriesPaint(0, Color.BLUE);
try {
response.setContentType("image/png");
OutputStream os = response.getOutputStream();
int height = dataset.getColumnCount()*45 + 65;
ChartUtilities.writeChartAsPNG(os, chart, 500, height);
os.close();
} catch (IOException e) {
System.err.println("Problem occurred creating chart.");
}
}













