相对于javaFX中屏幕坐标的插入位置

时间:2014-04-05 12:36:58

标签: textarea screen javafx-8 caret

我正在尝试找到一种方法来获取JavaFX中文本区域中插入位置的相应屏幕位置。我需要位置在插入位置以文本形式显示弹出窗口。

我在这里找到了请求或者它: https://bugs.openjdk.java.net/browse/JDK-8090849

以及一些解决方法: https://community.oracle.com/thread/2534556

他们以某种方式工作,但有时候位置无法正确更新存在一些问题。有没有人建议如何在屏幕X和Y方面获得插入位置?

2 个答案:

答案 0 :(得分:2)

只想跟进JavaFX中TextField控件的这个问题的答案。我确信同样适用于其他文本输入控件。我从查看一些涉及使用TextFieldSkin类的子类更改插入符的默认颜色的代码中获得了这个想法。如果仔细观察,TextFieldSkin超类将保存对Path实例的引用,该实例表示名为caretPath的受保护字段中的插入符号。虽然这是一种黑客解决方案,但它确实以比我在那里看到的大多数黑客更安全的方式为开发人员提供了Caret的绝对坐标。

public class TextFieldCaretControlSkin extends TextFieldSkin {
    public TextFieldCaretControlSkin(TextField textField, Stage stage) {
        super(textField);
        Popup popup = new Popup();

        // Make the popup appear to the right of the caret
        popup.setAnchorLocation(PopupWindow.AnchorLocation.CONTENT_BOTTOM_LEFT);
        // Make sure its position gets corrected to stay on screen if we go out of screen
        popup.setAutoFix(true);
        // Add list view (mock autocomplete popup)
        popup.getContent().add(new ListView<String>());

        // listen for changes in the layout bounds of the caret path
        caretPath.layoutBoundsProperty().addListener(new ChangeListener<Bounds>() {
            @Override
            public void changed(ObservableValue<? extends Bounds> observable, 
                                Bounds oldValue, Bounds newValue) {
                popup.hide();
                // get the caret's x position relative to the textfield.
                double x = newValue.getMaxX(); 
                // get the caret's y position relative to the textfield.
                double y = newValue.getMaxY(); 
                Point2D p = caretPath.localToScene(x, y);

                /*
                 * If the coordinates are negatives then the Path is being
                 * redrawn and we should just skip further processing.
                 */
                if (x == -1.0 || y == -1.0)
                    return;

                // show the popup at these absolute coordinates.                    
                popup.show(textField,
                        p.getX() + caretPath.getScene().getX() + 
                             caretPath.getScene().getWindow().getX(),
                        p.getY() + caretPath.getScene().getY() + 
                             caretPath.getScene().getWindow().getY() - 
                             newValue.getHeight()); // put the popup on top of the caret
            }
        });
    }
}

要使用你,必须将其嵌入某种子类文本输入控件中,并记住要textField.setSkin(new TextFieldCaretControlSkin(textField))。可能有更好的方法可以做到这一点,因为我不是JavaFX专家,但我只是想与世界其他地方分享这个解决方案,以防它提供了一些见解。

希望这有帮助!

答案 1 :(得分:1)

这是您使用RichTextFX将弹出窗口4px定位到插入符右侧的方法:

InlineCssTextArea area = new InlineCssTextArea();
Popup popup = new Popup();
popup.getContent().add(new Label("I am a popup label!"));
area.setPopupWindow(popup);
area.setPopupAlignment(PopupAlignment.CARET_CENTER);
area.setPopupAnchorOffset(new Point2D(4, 0));

您仍需要通过调用

来自行控制弹出窗口的可见性
popup.show(ownerWindow);
popup.hide();

另见working demo

相关问题