如何获取用于显示 PopupControl 的 javaFX 节点的 X 和 Y 位置?

Jer*_*gar 3 java

我创建了一个与 DatePicker 类类似的 JavaFX 类,但它显示一个弹出窗口,其中包含选择时间的方法。我想让弹出窗口出现在 TextField 和 Button 下方,就像 DatePicker 弹出窗口一样,但我无法找到获取节点的 X 和 Y 坐标的方法。任何帮助,将不胜感激。

jew*_*sea 5

您可以使用以下方法获取屏幕坐标:node.localToScreen(x,y)

以下代码将弹出窗口的左上角定位(锚定)在弹出所有者窗口上节点的底部中心:

Point2D anchorPoint = node.localToScreen(
        node.getWidth() / 2,
        node.getHeight()
);

popup.setAnchorLocation(
        PopupWindow.AnchorLocation.WINDOW_TOP_LEFT
);

popup.show(
        node,
        anchorPoint.getX(),
        anchorPoint.getY()
);
Run Code Online (Sandbox Code Playgroud)

应用示例:

显示和隐藏位于控制按钮底部中心的弹出窗口。

第三定律

import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.geometry.*;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.StackPane;
import javafx.stage.*;

public class Popcorn extends Application {
    @Override
    public void start(Stage stage) {
        StackPane popupLayout = new StackPane(
                new Label(
                        "Clarke's third law\nAny sufficiently advanced technology is indistinguishable from magic."
                )
        );
        popupLayout.setStyle("-fx-opacity: 0.8; -fx-background-color: paleturquoise;");
        popupLayout.setPadding(new Insets(10));

        Popup popup = new Popup();
        popup.getContent().add(
                popupLayout
        );
        popupLayout.setOnMouseClicked(event -> popup.hide());

        ToggleButton showPopupButton = new ToggleButton("Show popup");

        showPopupButton.textProperty().bind(
                Bindings.when(showPopupButton.selectedProperty())
                        .then("Hide popup")
                        .otherwise("Show popup")
        );

        showPopupButton.selectedProperty().addListener((observable, wasSelected, isSelected) -> {
            if (isSelected) {
                showPopup(popup, showPopupButton);
            } else {
                popup.hide();
            }
        });

        popup.setOnShown(event -> showPopupButton.setSelected(true));
        popup.setOnHidden(event -> showPopupButton.setSelected(false));

        StackPane stageLayout = new StackPane(showPopupButton);
        stageLayout.setPadding(new Insets(10));
        stage.setScene(new Scene(stageLayout));
        stage.show();
    }

    private void showPopup(Popup popup, Control ownerNode) {
        Point2D anchorPoint = ownerNode.localToScreen(
                ownerNode.getWidth() / 2,
                ownerNode.getHeight()
        );

        popup.setAnchorLocation(
                PopupWindow.AnchorLocation.WINDOW_TOP_LEFT
        );

        popup.show(
                ownerNode,
                anchorPoint.getX(),
                anchorPoint.getY()
        );
    }

    public static void main(String[] args) {
        launch(args);
    }
}
Run Code Online (Sandbox Code Playgroud)

关于弹出锚点的注释

弹出窗口锚点只是向弹出窗口系统提供弹出窗口放置位置的建议。JavaFX 中内置的弹出逻辑足够智能,可以知道弹出窗口的大小及其在屏幕上的初始位置。如果这意味着屏幕上没有足够的空间来在建议的锚点处显示弹出窗口,则弹出窗口实现将自动调整锚点以确保弹出窗口在首次显示时完全可见。您可以通过运行示例代码并将所有者阶段放置在屏幕的最底部或右侧来尝试此操作,然后再尝试显示弹出窗口。