如何使用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);
            }
        });
    }
}

我的猜测是,您的鼠标侦听器在(内部)JFreeCharts侦听器之前被调用,因此当您的代码执行时,交叉点还没有更新(仍然指向上一个选择)。将chartMouseClicked代码放入invokeLater应该可以解决这个问题。

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

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

尝试从ChartMouseEvent e:中提取

e.x
e.y

e.getTrigger().getX()

为我工作!

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

相关内容

  • 没有找到相关文章

最新更新