如何确定javafx';监视器上的s折线图峰值位置

如何确定javafx';监视器上的s折线图峰值位置,java,javafx,charts,location,Java,Javafx,Charts,Location,基本上,当我将鼠标悬停在某个峰值上时,我希望显示带有一些额外信息的工具提示 然而,我猜不出如何在监视器上获得峰值的位置(因为工具提示要求监视器的绝对坐标) 这是我当前的代码 //dateNumberData is the peak Tooltip tooltip = new Tooltip(); //Here i just edit tooltip info dateNumberData.getNode().setOnMouseEntered(event -> { tooltip

基本上,当我将鼠标悬停在某个峰值上时,我希望显示带有一些额外信息的工具提示

然而,我猜不出如何在监视器上获得峰值的位置(因为工具提示要求监视器的绝对坐标)

这是我当前的代码

//dateNumberData is the peak

Tooltip tooltip = new Tooltip();
//Here i just edit tooltip info
dateNumberData.getNode().setOnMouseEntered(event -> {
    tooltip.show(dateNumberData.getNode(),
        dateNumberData.getNode().localToScreen(dateNumberData.getNode().getLayoutX(), 0).getX(),
        dateNumberData.getNode().localToScreen(0, dateNumberData.getNode().getLayoutY()).getY());
    });
dateNumberData.getNode().setOnMouseExited(event -> tooltip.hide());
但是工具提示到处都是。如果我使用
dateNumberData.getNode().getParent().localToScreen()
工具提示根本就不会出现(但tooltip.getX()返回的坐标相当正确。至少它应该与这些坐标一起出现)

这里使用的
layoutX()
layoutY()
属性不正确。这些可能是父节点中节点的坐标,但您不知道通过设置这些坐标来定位节点:例如,它可能使用平移或其他布局机制。而是使用
getBoundsInLocal()
,然后变换边界

在工具提示中添加一个小偏移也是一个好主意:这不仅看起来更好,而且可以防止工具提示遮挡节点,这意味着您触发鼠标退出,并以重复循环结束

dateNumberData.getNode().setOnMouseEntered(event -> {

    Bounds bounds = dateNumberData.getNode().localToScreen(dateNumberData.getNode().getBoundsInLocal());
    tooltip.show(dateNumberData.getNode(),
        bounds.getMaxX()+15,
        bounds.getMaxY()+5);
    });
以下是SSCCE:

import java.util.Random;

import javafx.application.Application;
import javafx.geometry.Bounds;
import javafx.scene.Scene;
import javafx.scene.chart.LineChart;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart.Data;
import javafx.scene.chart.XYChart.Series;
import javafx.scene.control.Tooltip;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;

public class LineChartWithTooltip extends Application {

    @Override
    public void start(Stage primaryStage) {
        LineChart<Number, Number> chart = new LineChart<>(new NumberAxis(), new NumberAxis());
        Series<Number, Number> series = new Series<>();
        series.setName("Data");
        Random rng = new Random();
        for (int i = 0 ; i <= 10; i++) {
            series.getData().add(new Data<>(i, rng.nextDouble()));
        }
        chart.getData().add(series);

        Tooltip tooltip = new Tooltip();
        for (Data<Number, Number> d : series.getData()) {
            d.getNode().setOnMouseEntered(event -> {
                tooltip.setText(String.format("[%d, %.3f]", d.getXValue().intValue(), d.getYValue().doubleValue()));
                Bounds nodeBounds = d.getNode().getBoundsInLocal();
                Bounds nodeBoundsInScreen = d.getNode().localToScreen(nodeBounds);
                tooltip.show(d.getNode(),
                        nodeBoundsInScreen.getMaxX()+15,
                        nodeBoundsInScreen.getMaxY()+5);
                    });
            d.getNode().setOnMouseExited(event -> tooltip.hide());
        }

        primaryStage.setScene(new Scene(new BorderPane(chart), 600, 600));
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}
import java.util.Random;
导入javafx.application.application;
导入javafx.geometry.Bounds;
导入javafx.scene.scene;
导入javafx.scene.chart.LineChart;
导入javafx.scene.chart.NumberAxis;
导入javafx.scene.chart.XYChart.Data;
导入javafx.scene.chart.XYChart.Series;
导入javafx.scene.control.Tooltip;
导入javafx.scene.layout.BorderPane;
导入javafx.stage.stage;
带有工具提示的公共类LineChart扩展了应用程序{
@凌驾
公共无效开始(阶段primaryStage){
线形图=新线形图(新编号轴(),新编号轴());
系列=新系列();
series.setName(“数据”);
随机rng=新随机();
对于(int i=0;i{
tooltip.setText(String.format(“[%d,%.3f]”),d.getXValue().intValue(),d.getYValue().doubleValue());
Bounds nodeBounds=d.getNode().getBoundsInLocal();
Bounds nodeBoundsInScreen=d.getNode().localToScreen(nodeBounds);
tooltip.show(d.getNode(),
nodeBoundsInScreen.getMaxX()+15,
nodeBoundsInScreen.getMaxY()+5);
});
d、 getNode().setOnMouseExited(事件->工具提示.hide());
}
设置场景(新场景(新边框窗格(图表),600600));
primaryStage.show();
}
公共静态void main(字符串[]args){
发射(args);
}
}
此处使用的
layoutX()
layoutY()
属性不正确。这些可能是父节点中节点的坐标,但您不知道通过设置这些坐标来定位节点:例如,它可能使用平移或其他布局机制。而是使用
getBoundsInLocal()
,然后变换边界

在工具提示中添加一个小偏移也是一个好主意:这不仅看起来更好,而且可以防止工具提示遮挡节点,这意味着您触发鼠标退出,并以重复循环结束

dateNumberData.getNode().setOnMouseEntered(event -> {

    Bounds bounds = dateNumberData.getNode().localToScreen(dateNumberData.getNode().getBoundsInLocal());
    tooltip.show(dateNumberData.getNode(),
        bounds.getMaxX()+15,
        bounds.getMaxY()+5);
    });
以下是SSCCE:

import java.util.Random;

import javafx.application.Application;
import javafx.geometry.Bounds;
import javafx.scene.Scene;
import javafx.scene.chart.LineChart;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart.Data;
import javafx.scene.chart.XYChart.Series;
import javafx.scene.control.Tooltip;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;

public class LineChartWithTooltip extends Application {

    @Override
    public void start(Stage primaryStage) {
        LineChart<Number, Number> chart = new LineChart<>(new NumberAxis(), new NumberAxis());
        Series<Number, Number> series = new Series<>();
        series.setName("Data");
        Random rng = new Random();
        for (int i = 0 ; i <= 10; i++) {
            series.getData().add(new Data<>(i, rng.nextDouble()));
        }
        chart.getData().add(series);

        Tooltip tooltip = new Tooltip();
        for (Data<Number, Number> d : series.getData()) {
            d.getNode().setOnMouseEntered(event -> {
                tooltip.setText(String.format("[%d, %.3f]", d.getXValue().intValue(), d.getYValue().doubleValue()));
                Bounds nodeBounds = d.getNode().getBoundsInLocal();
                Bounds nodeBoundsInScreen = d.getNode().localToScreen(nodeBounds);
                tooltip.show(d.getNode(),
                        nodeBoundsInScreen.getMaxX()+15,
                        nodeBoundsInScreen.getMaxY()+5);
                    });
            d.getNode().setOnMouseExited(event -> tooltip.hide());
        }

        primaryStage.setScene(new Scene(new BorderPane(chart), 600, 600));
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}
import java.util.Random;
导入javafx.application.application;
导入javafx.geometry.Bounds;
导入javafx.scene.scene;
导入javafx.scene.chart.LineChart;
导入javafx.scene.chart.NumberAxis;
导入javafx.scene.chart.XYChart.Data;
导入javafx.scene.chart.XYChart.Series;
导入javafx.scene.control.Tooltip;
导入javafx.scene.layout.BorderPane;
导入javafx.stage.stage;
带有工具提示的公共类LineChart扩展了应用程序{
@凌驾
公共无效开始(阶段primaryStage){
线形图=新线形图(新编号轴(),新编号轴());
系列=新系列();
series.setName(“数据”);
随机rng=新随机();
对于(int i=0;i{
tooltip.setText(String.format(“[%d,%.3f]”),d.getXValue().intValue(),d.getYValue().doubleValue());
Bounds nodeBounds=d.getNode().getBoundsInLocal();
Bounds nodeBoundsInScreen=d.getNode().localToScreen(nodeBounds);
tooltip.show(d.getNode(),
nodeBoundsInScreen.getMaxX()+15,
nodeBoundsInScreen.getMaxY()+5);
});
d、 getNode().setOnMouseExited(事件->工具提示.hide());
}
设置场景(新场景(新边框窗格(图表),600600));
primaryStage.show();
}
公共静态void main(字符串[]args){
发射(args);
}
}

我知道我需要添加一些偏移量,我打算稍后再添加,但我实际上没有想到它会重叠节点并触发
onMouseExited()
这可能就是为什么
.getParent()的代码没有显示任何工具提示,并且我在这里添加的调试输出被垃圾邮件发送…所以这就解决了问题?还是不?从你的评论我看不出来。我更新了一个完整的例子。终于有时间检查了。是的,问题解决了
.getParent()
+添加一些偏移量trickI知道我需要添加一些偏移量吗,我稍后会添加,但我实际上没有想到它会重叠节点并触发
onMouseExited()
,这可能就是代码与
.getParent()重叠的原因
没有显示任何工具提示,我在这里添加的调试输出被垃圾发送……所以这就解决了吗?还是不?从你的评论我看不出来。我更新了一个完整的例子。终于有时间检查了。是的,问题解决了
.getParent()
+添加一些偏移量就成功了