简体   繁体   English

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

[英]How to get the coordinates of a point on mouse click with JFreeChart?

I am trying to get the coordinates of the point clicked with the mouse on a scatter plot graph. 我试图在散点图图上用鼠标点击点的坐标。

When you click on a point, "Click event!" 单击某个点时,“单击事件!” and the coordinates are printed on the console. 并在控制台上打印坐标。 When you click on the "Test" button, "Test" and the coordinates are printed on the console. 当您单击“测试”按钮时,“测试”并在控制台上打印坐标。

Problem: The coordinates printed after clicking the button are up-to-date. 问题:单击按钮后打印的坐标是最新的。 The coordinates printed after clicking on a point are the one of the previously selected point . 单击一个点后打印的坐标是先前选择的点之一

How can I fix that (so when I click on a point, the coordinates of the new selected point are displayed) ? 我该如何解决这个问题(所以当我点击一个点时,会显示新选定点的坐标)?

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

My guess is that your mouse listener gets called before the (internal) JFreeCharts listener is, so the cross hair point is not yet updated when your code executes (point to the previous selection still). 我的猜测是你的鼠标监听器在(内部)JFreeCharts监听器之前被调用,所以当你的代码执行时,交叉发点还没有更新(指向前一个选择)。 Putting your chartMouseClicked code in an invokeLater should fix that. 将chartMouseClicked代码放在invokeLater中应该解决这个问题。

The problem is that the redrawing of the chart is also triggered by the mouse event and so it is not assured that this has finished at the time your event listener is triggered. 问题是图表的重绘也是由鼠标事件触发的,因此无法确保在触发事件监听器时这已完成。

You should listen to another point which guarantees the redraw is finished. 你应该听另一个保证重绘完成的点。 You can use the chartProgressListener and filter out when the redrawing has completed. 您可以使用chartProgressListener并在重绘完成时过滤掉。 The adapted code isn't very elegant and you might need some more checks, but it seems to do the job: 改编的代码不是很优雅,你可能需要更多的检查,但它似乎做的工作:

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

e.getTrigger().getX() e.getTrigger()。的getX()

worked for me! 为我工作!

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

Try extracting from ChartMouseEvent e: 尝试从ChartMouseEvent中提取e:

e.x
e.y

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM