我试图在散点图图上用鼠标点击点的坐标。
当您点击某个点时,“点击活动!”并在控制台上打印坐标。 当您单击“测试”按钮时,“测试”并在控制台上打印坐标。
问题:点击按钮后打印的坐标是最新的。单击某个点后打印的坐标是之前选择的点。
我该如何解决这个问题(所以当我点击一个点时,会显示新选定点的坐标)?
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);
}
});
}
}
答案 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() );