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

问题描述 投票:0回答:3

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

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

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

它们以某种方式工作,但有时会出现一些位置无法正确更新的问题。有人建议如何根据屏幕 X 和 Y 获取插入符位置吗?

textarea screen javafx-8 caret
3个回答
3
投票

只是想跟进 JavaFX 中 TextField 控件的这个问题的答案。我确信同样的情况也适用于其他文本输入控件。我通过查看一些涉及使用

TextFieldSkin
类的子类更改插入符号的默认颜色的代码得到了这个想法。如果仔细观察,
TextFieldSkin
超类保存对
Path
实例的引用,该实例表示名为
caretPath
的受保护字段中的插入符号。尽管这是一种黑客解决方案,但它确实以比我见过的大多数黑客更安全的方式为开发人员提供了插入符的绝对坐标。

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
投票

这就是如何使用 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();

另请参阅此工作演示


0
投票

您能否让我了解有关这些方法的更多信息?似乎无法找到他们。它们来自哪个版本?

    area.setPopupWindow(popup);
    area.setPopupAlignment(PopupAlignment.CARET_CENTER);
    area.setPopupAnchorOffset(new Point2D(4, 0));

提前非常感谢。

© www.soinside.com 2019 - 2024. All rights reserved.