如何使用JFreeChart鼠标单击获取点的坐标?

时间:2012-03-13 14:45:01

标签: java swing jfreechart

我试图在散点图图上用鼠标点击点的坐标。

当您点击某个点时,“点击活动!”并在控制台上打印坐标。 当您单击“测试”按钮时,“测试”并在控制台上打印坐标。

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

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

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);
            }
        });
    }
}

4 个答案:

答案 0 :(得分:6)

我的猜测是你的鼠标监听器在(内部)JFreeCharts监听器之前被调用,所以当你的代码执行时,交叉发点还没有更新(指向前一个选择)。将chartMouseClicked代码放在invokeLater中应该解决这个问题。

答案 1 :(得分:1)

问题是图表的重绘也是由鼠标事件触发的,因此无法确保在触发事件监听器时这已完成。

你应该听另一个保证重绘完成的点。您可以使用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);
        }
    });
    }
}

答案 2 :(得分:0)

尝试从ChartMouseEvent中提取e:

e.x
e.y

答案 3 :(得分:0)

e.getTrigger()。的getX()

为我工作!

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