【问题标题】:How to get the coordinates of a point on mouse click with JFreeChart?如何使用 JFreeChart 获取鼠标单击点的坐标?
【发布时间】:2012-03-13 14:45:00
【问题描述】:

我正在尝试在散点图上获取用鼠标单击的点的坐标。

当你点击一个点时,“点击事件!”并且坐标打印在控制台上。 当您点击“测试”按钮时,“测试”和坐标会打印在控制台上。

问题:点击按钮后打印的坐标是最新的。点击一个点后打印的坐标是先前选择的点之一。

我该如何解决这个问题(所以当我点击一个点时,会显示新选定点的坐标)?

package graph;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.util.Random;

import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartMouseEvent;
import org.jfree.chart.ChartMouseListener;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.axis.NumberTickUnit;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYItemRenderer;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;

/**
 * @see http://stackoverflow.com/questions/7231824
 * @see http://stackoverflow.com/questions/7205742
 * @see http://stackoverflow.com/questions/7208657
 * @see http://stackoverflow.com/questions/7071057
 */
public class GraphFrameOld extends JFrame {

    private static final int N = 32;
    private static final String title = "Scatter Plot Pannel";
    private static final Random rand = new Random();
    private final XYSeries added = new XYSeries("Added");

    private static XYPlot xyPlot;

    public GraphFrameOld(String s) {
        super(s);
        final ChartPanel chartPanel = createGraphPanel();

        this.add(chartPanel, BorderLayout.CENTER);
        JPanel control = new JPanel();
        control.add(new JButton(new AbstractAction("Add") {

            @Override
            public void actionPerformed(ActionEvent e) {
                for (int i = 0; i < N; i++) {
                    added.add(rand.nextDouble(), rand.nextDouble());
                }
            }
        }));

        control.add(new JButton(new AbstractAction("Test") {

            @Override
            public void actionPerformed(ActionEvent e) {
                System.out.println("Test");
                System.out.println(xyPlot.getDomainCrosshairValue() + " "
                        + xyPlot.getRangeCrosshairValue());

            }
        }));

        // add click event
        chartPanel.addChartMouseListener(new ChartMouseListener() {
            @Override
            public void chartMouseClicked(ChartMouseEvent e) {
                System.out.println("Click event!");
                XYPlot xyPlot2 = chartPanel.getChart().getXYPlot();
                  // Problem: the coordinates displayed are the one of the previously selected point !
                System.out.println(xyPlot2.getDomainCrosshairValue() + " "
                        + xyPlot2.getRangeCrosshairValue());
            }

            @Override
            public void chartMouseMoved(ChartMouseEvent arg0) {
            }
        });

        this.add(control, BorderLayout.SOUTH);
    }

    private ChartPanel createGraphPanel() {
        JFreeChart jfreechart = ChartFactory
                .createScatterPlot(title, "X", "Y", createSampleData(),
                        PlotOrientation.VERTICAL, true, true, false);
        xyPlot = (XYPlot) jfreechart.getPlot();
        xyPlot.setDomainCrosshairVisible(true);
        xyPlot.setRangeCrosshairVisible(true);
        XYItemRenderer renderer = xyPlot.getRenderer();
        renderer.setSeriesPaint(0, Color.blue);
        NumberAxis domain = (NumberAxis) xyPlot.getDomainAxis();
        domain.setRange(0.00, 1.00);
        domain.setTickUnit(new NumberTickUnit(0.1));
        domain.setVerticalTickLabels(true);
        NumberAxis range = (NumberAxis) xyPlot.getRangeAxis();
        range.setRange(0.0, 1.0);
        range.setTickUnit(new NumberTickUnit(0.1));
        return new ChartPanel(jfreechart);
    }

    private XYDataset createSampleData() {
        XYSeriesCollection xySeriesCollection = new XYSeriesCollection();
        XYSeries series = new XYSeries("Random");
        for (int i = 0; i < N * N; i++) {
            double x = rand.nextDouble();
            double y = rand.nextDouble();
            series.add(x, y);
        }
        xySeriesCollection.addSeries(series);
        xySeriesCollection.addSeries(added);
        return xySeriesCollection;
    }

    public static void main(String args[]) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                GraphFrameOld demo = new GraphFrameOld(title);
                demo.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                demo.pack();
                demo.setLocationRelativeTo(null);
                demo.setVisible(true);
            }
        });
    }
}

【问题讨论】:

    标签: java swing jfreechart


    【解决方案1】:

    我的猜测是您的鼠标侦听器在(内部)JFreeCharts 侦听器之前被调用,因此当您的代码执行时十字准线尚未更新(仍然指向先前的选择)。将您的 chartMouseClicked 代码放在 invokeLater 中应该可以解决这个问题。

    【讨论】:

      【解决方案2】:

      问题是图表的重绘也是由鼠标事件触发的,因此不能保证在触发事件侦听器时这已经完成。

      您应该听另一个保证重绘完成的要点。您可以使用 chartProgressListener 并在重绘完成时过滤掉。改编后的代码不是很优雅,您可能需要进行更多检查,但它似乎可以完成这项工作:

      package graph;
      
      import java.awt.BorderLayout;
      import java.awt.Color;
      import java.awt.EventQueue;
      import java.awt.event.ActionEvent;
      import java.awt.event.MouseEvent;
      import java.util.Random;
      
      import javax.swing.AbstractAction;
      import javax.swing.JButton;
      import javax.swing.JFrame;
      import javax.swing.JPanel;
      
      import org.jfree.chart.ChartFactory;
      import org.jfree.chart.ChartMouseEvent;
      import org.jfree.chart.ChartMouseListener;
      import org.jfree.chart.ChartPanel;
      import org.jfree.chart.JFreeChart;
      import org.jfree.chart.axis.NumberAxis;
      import org.jfree.chart.axis.NumberTickUnit;
      import org.jfree.chart.entity.ChartEntity;
      import org.jfree.chart.event.*;
      import org.jfree.chart.plot.PlotOrientation;
      import org.jfree.chart.plot.XYPlot;
      import org.jfree.chart.renderer.xy.XYItemRenderer;
      import org.jfree.data.xy.XYDataset;
      import org.jfree.data.xy.XYSeries;
      import org.jfree.data.xy.XYSeriesCollection;
      
      /**
       * @see http://stackoverflow.com/questions/7231824
       * @see http://stackoverflow.com/questions/7205742
       * @see http://stackoverflow.com/questions/7208657
       * @see http://stackoverflow.com/questions/7071057
       */
      public class GraphFrameOld extends JFrame {
      
          private static final int N = 32;
          private static final String title = "Scatter Plot Pannel";
          private static final Random rand = new Random();
          private final XYSeries added = new XYSeries("Added");
      
          private static XYPlot xyPlot;
      
          public GraphFrameOld(String s) {
          super(s);
          final ChartPanel chartPanel = createGraphPanel();
      
          this.add(chartPanel, BorderLayout.CENTER);
          JPanel control = new JPanel();
          control.add(new JButton(new AbstractAction("Add") {
      
              @Override
              public void actionPerformed(ActionEvent e) {
              for (int i = 0; i < N; i++) {
                  added.add(rand.nextDouble(), rand.nextDouble());
              }
              }
          }));
      
          control.add(new JButton(new AbstractAction("Test") {
      
              @Override
              public void actionPerformed(ActionEvent e) {
              System.out.println("Test");
              System.out.println(xyPlot.getDomainCrosshairValue() + " "
                  + xyPlot.getRangeCrosshairValue());
      
              }
          }));
      
      
      
          this.add(control, BorderLayout.SOUTH);
          }
      
          private ChartPanel createGraphPanel() {
          JFreeChart jfreechart = ChartFactory
              .createScatterPlot(title, "X", "Y", createSampleData(),
                  PlotOrientation.VERTICAL, true, true, false);
      
      
      
          xyPlot = (XYPlot) jfreechart.getPlot();
          xyPlot.setDomainCrosshairVisible(true);
          xyPlot.setRangeCrosshairVisible(true);
          XYItemRenderer renderer = xyPlot.getRenderer();
          renderer.setSeriesPaint(0, Color.red);
          NumberAxis domain = (NumberAxis) xyPlot.getDomainAxis();
          domain.setRange(0.00, 1.00);
      
          domain.setTickUnit(new NumberTickUnit(0.1));
          domain.setVerticalTickLabels(true);
          NumberAxis range = (NumberAxis) xyPlot.getRangeAxis();
          range.setRange(0.0, 1.0);
          range.setTickUnit(new NumberTickUnit(0.1));
          final ChartPanel result = new ChartPanel(jfreechart);
      
             jfreechart.addProgressListener(new ChartProgressListener() {
      
              @Override
              public void chartProgress(ChartProgressEvent cpe) {
              if(cpe.getType()==ChartProgressEvent.DRAWING_FINISHED){
               System.out.println("Click event!");
              XYPlot xyPlot2 = result.getChart().getXYPlot();
              System.out.println(xyPlot2.getDomainCrosshairValue() + " "
                  + xyPlot2.getRangeCrosshairValue());
              }
              }
          });
      
      
          return result;
          }
      
          private XYDataset createSampleData() {
          XYSeriesCollection xySeriesCollection = new XYSeriesCollection();
          XYSeries series = new XYSeries("Random");
          for (int i = 0; i < N * N; i++) {
              double x = rand.nextDouble();
              double y = rand.nextDouble();
              series.add(x, y);
          }
          xySeriesCollection.addSeries(series);
          xySeriesCollection.addSeries(added);
          return xySeriesCollection;
          }
      
          public static void main(String args[]) {
          EventQueue.invokeLater(new Runnable() {
      
              @Override
              public void run() {
              GraphFrameOld demo = new GraphFrameOld(title);
              demo.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
              demo.pack();
              demo.setLocationRelativeTo(null);
              demo.setVisible(true);
              }
          });
          }
      }
      

      【讨论】:

        【解决方案3】:

        尝试从 ChartMouseEvent e 中提取:

        e.x
        e.y
        

        【讨论】:

        • 我试过e.getChart().getXYPlot().getDomainCrosshairValue()。同样的问题
        【解决方案4】:

        e.getTrigger().getX()

        为我工作!

        System.out.println(e.getTrigger().getX() + " " + e.getTrigger().getY() );
        

        【讨论】:

          猜你喜欢
          • 2010-12-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-02-10
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多