Gráficos com interação do usuário [Resolvido]

5 respostas
anakromeiro

Olá gente,

bom, é a primeira vez que posto aqui e gostaria de ajuda com um problema…

Eu estou desenvolvendo um software que gera gráficos (gráfico de linha, barra, curva normal, etc) e estou usando o JFreeChart, mas o meu problema é que eu preciso gerar um gráfico onde o usuário possa clicar em cima de um ponto que foi plotado no gráfico e que eu consiga pegar esses pontos pra realizar algum processamento. Quando eu gero pelo JFreeChart, as únicas propriedades são de zoom e alterar cor da linha e essas coisas.

Alguém sabe se com o JFreeChart eu consigo fazer isso ou se existe alguma outra API que me permita gerar gráficos onde o usuário possa pelo menos clicar nos pontos?

Obrigada.

5 Respostas

R

Acho que você está exibindo seu gráfico num ChartPanel, correto? Supondo que ele se chama [painel], talvez os trechos de código abaixo ajudem:

// Remove as rotinas padrão para processamento de cliques do mouse
MouseListener ml[] = painel.getMouseListeners();

if (ml != null) {
  for (int i = 0; i < ml.length; i++) {
    painel.removeMouseListener(ml[i]);
  }
}

// Registra rotinas especializadas para processar cliques e
// movimentação do mouse sobre o gráfico
ChartMouseListener cml = new ChartMouseListener() {
  public void chartMouseClicked(ChartMouseEvent chartMouseEvent) {
    // Sua rotina aqui
  }

  public void chartMouseMoved(ChartMouseEvent chartMouseEvent) {
    // Sua rotina aqui
  }
};

painel.addChartMouseListener(cml);
anakromeiro

roger_rf eu estou exibindo em um ChartPanel sim.

O que você me sugeriu funcionou sim para pegar os pontos quando o usuário clica :smiley: , mas o problema é que eu consigo pegar qualquer ponto na área do gráfico, e não somente os que pertencem à linha do gráfico que foi traçada, por exemplo.
O que eu tô querendo é que quando ele clique em cima da linha do gráfico eu consiga pegar o valor correspondente do eixo X e o valor do eixo Y.

Já pesquisei muito sobre o JFreeChart mas até agora não consegui encontrar nada relacionado a isso… mas tô tentando ainda.

R

Experimente chamar a rotina abaixo em chartMouseMoved(). Ela supõe que seu gráfico se chama [chart] e que este é um ScatterPlot, que o plot do gráfico é um XYPlot e que os eixos X e Y são instâncias de NumberAxis.

private void processaMovimentacaoMouse(ChartMouseEvent event) {
  MouseEvent me = event.getTrigger();
  Rectangle2D rect = painel.getScreenDataArea();

  // Evento ocorreu dentro da área do gráfico?
  int xMouse = me.getX();
  int yMouse = me.getY();

  int xMin = (int) rect.getMinX();
  int yMin = (int) rect.getMinY();
  int xMax = (int) rect.getMaxX();
  int yMax = (int) rect.getMaxY();

  if ((xMouse < xMin) || (xMouse > xMax) ||
      (yMouse < yMin) || (yMouse > yMax)) {
    return;
  }

  // Gráfico visível?
  if ((xMin >= xMax) || (yMin >= yMax)) return;

  // Converte os pontos para as coordenadas reais
  XYPLot plot = (XYPlot) chart.getPlot();
  NumberAxis eixoX = (NumberAxis) plot.getDomainAxis();
  NumberAxis eixoY = (NumberAxis) plot.getRangeAxis();

  double difEixoX = eixoX.getUpperBound() - eixoX.getLowerBound();
  double difEixoY = eixoY.getUpperBound() - eixoY.getLowerBound();
  double deslocX = (double) (xMouse - xMin) / (double) (xMax - xMin);
  double deslocY = (double) (((yMax - yMin) - (yMouse - yMin))) /
                     (double) (yMax - yMin);
  double coordX = eixoX.getLowerBound() + (deslocX * difEixoX);
  double coordY = eixoY.getLowerBound() + (deslocY * difEixoY);

  // ... Usar [coordX] e [coordY] ...
}
anakromeiro

roger_rf, muito obrigada pela ajuda, mas acho que consegui resolver o problema.

O que eu fiz foi o seguinte: quando eu crio o gráfico, utilizei os métodos

plot = (XYPlot) chart.getPlot();

plot.setDomainCrosshairVisible(true);
plot.setRangeCrosshairVisible(true);

Isso faz com que quando o usuário clica em cima da linha do gráfico, ele faz uma reta marcando o ponto no eixo X e no eixo Y (e ainda posso definir se ele irá deixar clicar somente nos pontos que foram plotados no gráfico ou em qualquer ponto existente)

plot.setDomainCrosshairLockedOnData(true);

Depois foi só implementar o método abaixo:

chart.addProgressListener(new ChartProgressListener() {
            @Override
            public void chartProgress(ChartProgressEvent e) {               
                // Meu código
            }
        });
R

Excelente :slight_smile:

Criado 1 de março de 2012
Ultima resposta 2 de mar. de 2012
Respostas 5
Participantes 2