2014-04-05 3 views
3

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

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

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

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

ответ

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, но я просто хотел поделиться этим решением с остальным миром на всякий случай, если бы он дал некоторое представление.

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

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.

+0

спасибо Томасу! Это очень аккуратное решение! – melkhaldi

Смежные вопросы