Javafx 2 从javaFX折线图中的CategoryAxis检索字符串值-CategoryAxis javaFX 2.2.3.getValueForDisplay中的bug(双显示位置)-

Javafx 2 从javaFX折线图中的CategoryAxis检索字符串值-CategoryAxis javaFX 2.2.3.getValueForDisplay中的bug(双显示位置)-,javafx-2,linechart,Javafx 2,Linechart,我有一个JavaFXline图表,上面有月份和数值。每次单击图表时,我都试图在控制台中打印月份和折线图中的值。问题是,当我在我的CategoryAxis对象中调用方法getValueForDisplay时,它返回null 当我点击(x,y):1月3日 我要打印: X值=一月Y值:3 但程序正在打印: X值=**null**Y值:2.7796610169491527 另一个问题 2) 为什么在尝试打印坐标时,它似乎未校准(如果我单击3打印程序2.779661016949152?您可以在检查控制台上

我有一个JavaFXline图表,上面有月份和数值。每次单击图表时,我都试图在控制台中打印月份和折线图中的值。问题是,当我在我的
CategoryAxis
对象中调用方法
getValueForDisplay
时,它返回
null

当我点击(x,y):1月3日
我要打印:
X值=一月Y值:3

但程序正在打印:
X值=**null**Y值:2.7796610169491527

另一个问题
2) 为什么在尝试打印坐标时,它似乎未校准(如果我单击3打印程序
2.779661016949152
?您可以在检查控制台上打印的值时注意到此问题

以下是我正在使用的代码:

public class LineChartTest extends Application {
String xValue;
Number yValue;
private void init(Stage primaryStage) {
    Group root = new Group();
    primaryStage.setScene(new Scene(root));
    final CategoryAxis xAxis = new CategoryAxis();

    final NumberAxis yAxis = new NumberAxis("Values for Y-Axis", 0, 3, 1);

    yAxis.setUpperBound(5);

    ObservableList<XYChart.Series<String,Double>> lineChartData = FXCollections.observableArrayList(
        new LineChart.Series<String,Double>("en", FXCollections.observableArrayList(
            new XYChart.Data<String,Double>("jan", 1.0),
            new XYChart.Data<String,Double>("feb", 2.0),
            new XYChart.Data<String,Double>("mar", 3.0),
            new XYChart.Data<String,Double>("apr", 4.0),
            new XYChart.Data<String,Double>("may", 0.5)
        )),
        new LineChart.Series<String,Double>("to", FXCollections.observableArrayList(
            new XYChart.Data<String,Double>("jan", 1.6),
            new XYChart.Data<String,Double>("feb", 0.4),
            new XYChart.Data<String,Double>("mar", 2.9),
            new XYChart.Data<String,Double>("apr", 1.3),
            new XYChart.Data<String,Double>("may", 0.9)
        ))
    );


    //define a new line
    final Series<String,Double> otherSeries = new Series<String,Double>();
    //set points
    otherSeries.getData().add(new XYChart.Data("jan",3));
    otherSeries.getData().add(new XYChart.Data("feb",2));
    otherSeries.getData().add(new XYChart.Data("mar",4));
    //set name to the line
    otherSeries.setName("tre");
    //add the new line to the graph
    lineChartData.add(otherSeries);
    final LineChart chart = new LineChart(xAxis, yAxis, lineChartData);

    //set title to the figure
    chart.setTitle("Line Chart Test");

    root.getChildren().add(chart);

    chart.setOnMouseClicked(new EventHandler<MouseEvent>() {

          @Override
        public void handle(MouseEvent t) {

            //Why this seems to be not working properly?
            double sceneX = t.getSceneX();
            double sceneY = t.getSceneY();

            //gives the point of the graph
            xValue = xAxis.getValueForDisplay(sceneX);
            yValue = yAxis.getValueForDisplay(sceneY);


            System.out.println("sceneX-25: "+ sceneX);
            System.out.println("getDisplayPosition: " + xAxis.getValueForDisplay(sceneX));

            //Test
            System.out.println(" X value = " +  
            xValue + " Y value: " + yValue );  

            }
    });

}

@Override public void start(Stage primaryStage) throws Exception {
    init(primaryStage);
    primaryStage.show();


}


    public static void main(String[] args) {
        launch(args);
    }
}
您可以在此处找到源代码:

有两个问题

1)您使用了错误的坐标
getValueForDisplay
需要相对于图表绘图区域的坐标,而不是相对于场景的坐标

要解决这个问题,您可以使用下一个技巧

引入下一个递归调用以计算场景偏移:

private double xSceneShift(Node node) {
    return node.getParent() == null ? 0 : node.getBoundsInParent().getMinX() + xSceneShift(node.getParent());
}

private double ySceneShift(Node node) {
    return node.getParent() == null ? 0 : node.getBoundsInParent().getMinY() + ySceneShift(node.getParent());
}
查找图表绘图区域的偏移:

Node chartPlotBackground = chart.lookup(".chart-plot-background");
final double shiftX = xSceneShift(chartPlotBackground);
final double shiftY = ySceneShift(chartPlotBackground);
并在鼠标处理程序中使用它们:

public void handle(MouseEvent e) {
    double x = e.getSceneX() - shiftX;
    double y = e.getSceneY() - shiftY;

    xValue = xAxis.getValueForDisplay(x );
    yValue = yAxis.getValueForDisplay(y);

    System.out.println(" X value = "
                    + xValue + " \nY value: " + yValue);
}
2)您在
CategoryAxis
中遇到了一个问题,该问题已修复,但将在下一版本(8.0)中解决:

作为一种解决方法,您可以下载
CategoryAxis
源代码,将其重命名为
MyCategoryAxis
,并修复方法
getValueForDisplay()
中的一个错误——只需切换
getWidth()
getHeight()
调用的位置


如果要显示用户在图表上单击的数据点,则可以直接访问下划线数据。在本例中,将鼠标悬停到数据X-Y交点:

import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.scene.Cursor;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.chart.CategoryAxis;
import javafx.scene.chart.LineChart;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart;
import javafx.scene.control.Label;
import javafx.scene.control.LabelBuilder;
import javafx.scene.effect.DropShadow;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;
import javafx.stage.Stage;

public class ChartDemo extends Application {

    private DropShadow ds = new DropShadow();

    @Override
    public void start(Stage stage) {
        stage.setTitle("Linear plot");

        final CategoryAxis xAxis = new CategoryAxis();
        final NumberAxis yAxis = new NumberAxis(0, 22, 0.5);

        yAxis.setTickLabelFormatter(new NumberAxis.DefaultFormatter(yAxis) {
            @Override
            public String toString(Number object) {
                return String.format("%7.2f", object);
            }
        });
        final LineChart<String, Number> lineChart = new LineChart<String, Number>(xAxis, yAxis);

        lineChart.setCreateSymbols(true);
        lineChart.setAlternativeRowFillVisible(false);
        lineChart.setLegendVisible(false);

        final XYChart.Series series1 = new XYChart.Series();

        series1.getData().add(new XYChart.Data("Jan", 1));
        series1.getData().add(new XYChart.Data("Feb", 1.5));
        series1.getData().add(new XYChart.Data("Mar", 2));
        series1.getData().add(new XYChart.Data("Apr", 2.5));
        series1.getData().add(new XYChart.Data("May", 3));
        series1.getData().add(new XYChart.Data("Jun", 4));
        series1.getData().add(new XYChart.Data("Jul", 6));
        series1.getData().add(new XYChart.Data("Aug", 9));
        series1.getData().add(new XYChart.Data("Sep", 12));
        series1.getData().add(new XYChart.Data("Oct", 15));
        series1.getData().add(new XYChart.Data("Nov", 20));
        series1.getData().add(new XYChart.Data("Dec", 22));

        final Label lbl = LabelBuilder.create().font(Font.font("Arial", FontWeight.BOLD, 25))
                .textFill(Color.BLUEVIOLET).translateY(-200).build();
        StackPane pane = new StackPane();
        pane.getChildren().addAll(lineChart, lbl);
        Scene scene = new Scene(pane, 800, 600);
        lineChart.getData().addAll(series1);

        for (Object obj : series1.getData()) {
            final XYChart.Data data = (XYChart.Data) obj;
            final Node node = data.getNode();

            node.setOnMouseEntered(new EventHandler<MouseEvent>() {
                @Override
                public void handle(MouseEvent arg0) {
                    node.setEffect(ds);
                    node.setCursor(Cursor.HAND);
                    lbl.setText("X-value=" + data.getXValue().toString() + "\nY-value=" + data.getYValue().toString());
                    System.out.println("X-value=" + data.getXValue().toString() + ", Y-value=" + data.getYValue().toString());
                }
            });

            node.setOnMouseExited(new EventHandler<MouseEvent>() {
                @Override
                public void handle(MouseEvent arg0) {
                    node.setEffect(null);
                    node.setCursor(Cursor.DEFAULT);
                    lbl.setText("");
                }
            });
        }
        stage.setScene(scene);
        stage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}
导入javafx.application.application;
导入javafx.event.EventHandler;
导入javafx.scene.Cursor;
导入javafx.scene.Node;
导入javafx.scene.scene;
导入javafx.scene.chart.CategoryAxis;
导入javafx.scene.chart.LineChart;
导入javafx.scene.chart.NumberAxis;
导入javafx.scene.chart.XYChart;
导入javafx.scene.control.Label;
导入javafx.scene.control.LabelBuilder;
导入javafx.scene.effect.DropShadow;
导入javafx.scene.input.MouseEvent;
导入javafx.scene.layout.StackPane;
导入javafx.scene.paint.Color;
导入javafx.scene.text.Font;
导入javafx.scene.text.FontWeight;
导入javafx.stage.stage;
公共类ChartDemo扩展了应用程序{
私有DropShadow ds=新DropShadow();
@凌驾
公众假期开始(阶段){
阶段。片名(“线性图”);
最终CategoryAxis xAxis=新CategoryAxis();
最终数值轴yAxis=新数值轴(0,22,0.5);
yAxis.setTickLabelFormatter(新编号Axis.DefaultFormatter(yAxis){
@凌驾
公共字符串toString(数字对象){
返回String.format(“%7.2f”,对象);
}
});
最终线形图线形图=新线形图(xAxis,yAxis);
lineChart.setCreateSynumbles(true);
线形图.setAlternativeRowFillVisible(假);
线形图。setLegendVisible(假);
最终XYChart.Series系列1=新的XYChart.Series();
series1.getData().add(新的XYChart.Data(“Jan”,1));
series1.getData().add(新的XYChart.Data(“Feb”,1.5));
series1.getData().add(新的XYChart.Data(“Mar”,2));
series1.getData().add(新的XYChart.Data(“Apr”,2.5));
series1.getData().add(新的XYChart.Data(“May”,3));
series1.getData().add(新的XYChart.Data(“Jun”,4));
series1.getData().add(新的XYChart.Data(“Jul”,6));
series1.getData().add(新的XYChart.Data(“Aug”,9));
series1.getData().add(新的XYChart.Data(“Sep”,12));
series1.getData().add(新的XYChart.Data(“Oct”,15));
series1.getData().add(新的XYChart.Data(“Nov”,20));
series1.getData().add(新的XYChart.Data(“Dec”,22));
最终标签lbl=LabelBuilder.create().font(font.font(“Arial”,fontwweight.BOLD,25))
.textFill(Color.BLUEVIOLET).translateY(-200.build();
StackPane=新的StackPane();
pane.getChildren().addAll(折线图,lbl);
场景=新场景(窗格,800600);
lineChart.getData().addAll(series1);
对于(对象obj:series1.getData()){
最终的XYChart.Data数据=(XYChart.Data)obj;
最终节点=data.getNode();
setOnMouseCentered(新的EventHandler(){
@凌驾
公共无效句柄(MouseEvent arg0){
节点集效应(ds);
node.setCursor(Cursor.HAND);
lbl.setText(“X-value=“+data.getXValue().toString()+”\nY value=“+data.getYValue().toString());
System.out.println(“X-value=“+data.getXValue().toString()+”,Y-value=“+data.getYValue().toString());
}
});
setOnMouseExited(新的EventHandler(){
@凌驾
公共无效句柄(MouseEvent arg0){
node.setEffect(null);
node.setCursor(Cursor.DEFAULT);
lbl.setText(“”);
}
});
}
舞台场景;
stage.show();
}
公共静态void main(字符串[]args){
发射(args);
}
}

这是一个很好的解决方案,可以从系列中获得结果,非常感谢!。问题是我需要坐标系中任何位置的值,而不仅仅是序列中的值。至少现在我知道了如何在这种情况下获取字符串值,我真的很感激!多么漂亮的递归方法啊。我无法用语言表达我的感激之情,谢尔盖。格雷西亚斯格雷西亚斯格雷西亚斯!在递归函数中,我将添加以下内容以考虑填充:+(node instanceof
public void handle(MouseEvent e) {
    double x = e.getSceneX() - shiftX;
    double y = e.getSceneY() - shiftY;

    xValue = xAxis.getValueForDisplay(x );
    yValue = yAxis.getValueForDisplay(y);

    System.out.println(" X value = "
                    + xValue + " \nY value: " + yValue);
}
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.scene.Cursor;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.chart.CategoryAxis;
import javafx.scene.chart.LineChart;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart;
import javafx.scene.control.Label;
import javafx.scene.control.LabelBuilder;
import javafx.scene.effect.DropShadow;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;
import javafx.stage.Stage;

public class ChartDemo extends Application {

    private DropShadow ds = new DropShadow();

    @Override
    public void start(Stage stage) {
        stage.setTitle("Linear plot");

        final CategoryAxis xAxis = new CategoryAxis();
        final NumberAxis yAxis = new NumberAxis(0, 22, 0.5);

        yAxis.setTickLabelFormatter(new NumberAxis.DefaultFormatter(yAxis) {
            @Override
            public String toString(Number object) {
                return String.format("%7.2f", object);
            }
        });
        final LineChart<String, Number> lineChart = new LineChart<String, Number>(xAxis, yAxis);

        lineChart.setCreateSymbols(true);
        lineChart.setAlternativeRowFillVisible(false);
        lineChart.setLegendVisible(false);

        final XYChart.Series series1 = new XYChart.Series();

        series1.getData().add(new XYChart.Data("Jan", 1));
        series1.getData().add(new XYChart.Data("Feb", 1.5));
        series1.getData().add(new XYChart.Data("Mar", 2));
        series1.getData().add(new XYChart.Data("Apr", 2.5));
        series1.getData().add(new XYChart.Data("May", 3));
        series1.getData().add(new XYChart.Data("Jun", 4));
        series1.getData().add(new XYChart.Data("Jul", 6));
        series1.getData().add(new XYChart.Data("Aug", 9));
        series1.getData().add(new XYChart.Data("Sep", 12));
        series1.getData().add(new XYChart.Data("Oct", 15));
        series1.getData().add(new XYChart.Data("Nov", 20));
        series1.getData().add(new XYChart.Data("Dec", 22));

        final Label lbl = LabelBuilder.create().font(Font.font("Arial", FontWeight.BOLD, 25))
                .textFill(Color.BLUEVIOLET).translateY(-200).build();
        StackPane pane = new StackPane();
        pane.getChildren().addAll(lineChart, lbl);
        Scene scene = new Scene(pane, 800, 600);
        lineChart.getData().addAll(series1);

        for (Object obj : series1.getData()) {
            final XYChart.Data data = (XYChart.Data) obj;
            final Node node = data.getNode();

            node.setOnMouseEntered(new EventHandler<MouseEvent>() {
                @Override
                public void handle(MouseEvent arg0) {
                    node.setEffect(ds);
                    node.setCursor(Cursor.HAND);
                    lbl.setText("X-value=" + data.getXValue().toString() + "\nY-value=" + data.getYValue().toString());
                    System.out.println("X-value=" + data.getXValue().toString() + ", Y-value=" + data.getYValue().toString());
                }
            });

            node.setOnMouseExited(new EventHandler<MouseEvent>() {
                @Override
                public void handle(MouseEvent arg0) {
                    node.setEffect(null);
                    node.setCursor(Cursor.DEFAULT);
                    lbl.setText("");
                }
            });
        }
        stage.setScene(scene);
        stage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}