Положение каретки относительно координат экрана в javaFX

Я пытаюсь найти способ получить соответствующее расположение на экране позиции каретки в текстовой области в JavaFX. Мне нужно место для отображения всплывающих окон в тексте в месте каретки.

Я нашел запрос или его здесь: https://bugs.openjdk.java.net/browse/JDK-8090849

и некоторые обходные пути здесь: https://community.oracle.com/thread/2534556

Они как-то работают, но есть несколько проблем с неправильным обновлением местоположения. Есть ли у кого-нибудь предложение о том, как получить позицию каретки с точки зрения экрана X и Y?


person melkhaldi    schedule 05.04.2014    source источник


Ответы (2)


Просто хотел получить ответ на этот вопрос для элементов управления TextField в JavaFX. Я уверен, что то же самое можно применить и к другим элементам управления текстовым вводом. Я получил эту идею, просмотрев некоторый код, который включал изменение цвета каретки по умолчанию с использованием подкласса класса 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, но я просто хотел поделиться этим решением с остальным миром на случай, если оно даст некоторое представление.

Надеюсь это поможет!

person Nadeem Douba    schedule 21.05.2015

Вот как вы используете RichTextFX для размещения всплывающего окна на 4 пикселя справа от каретки:

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();

См. также этот рабочая демонстрация.

person Tomas Mikula    schedule 02.06.2014