JavaFX: поместите каретку/курсор в конец TextArea при переходе в TextArea

(При поиске в stackoverflow я видел, что этот вопрос адресован для Javascript, но не для JavaFX)

У меня есть TextArea, который фактически является основным текстовым редактором в приложении, подобном текстовому процессору (т. е. я предполагаю, что пользователь будет проводить много времени, работая внутри этого TextArea). Когда пользователь вводит вкладку в TextArea, я хотел бы, чтобы курсор был помещен в конец TextArea, чтобы пользователь мог продолжить редактирование с конца того, что он в последний раз набрал.

Я реализовал это с помощью ChangeListener (код ниже), и он имеет желаемое поведение. Однако, поскольку курсор помещается в конец TextArea каждый раз при получении фокуса, то, если бы я переключал приложения, а затем переключался обратно, курсор перемещался. Это неудобно, если, например, пользователь набирает предложение где-то в середине TextArea, переключается на чтение электронной почты, а затем переключается обратно и обнаруживает, что его курсор переместился.

Существует ли политика обхода фокуса, которая делает это или какой-либо другой способ реализовать это, чтобы курсор перемещался в конец только тогда, когда пользователь переходит в TextArea? Мне кажется, что это было бы обычно желаемым поведением: чтобы курсор всегда появлялся в конце TextArea всякий раз, когда TextArea находится на вкладке, но в противном случае оставлял курсор без движения.

TextArea passageTextArea;

passageTextArea.focusedProperty().addListener(new ChangeListener<Boolean>() {
    @Override
    public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue)
    {
        if (newValue.booleanValue()) {
            passageTextArea.positionCaret(passageTextArea.getText().length());
        }
    }
});

person skrilmps    schedule 19.05.2016    source источник


Ответы (2)


Вы можете добавить EventHandler вместо KeyEvent, который перемещает курсор в конец текста, когда вы нажимаете клавишу Tab:

 EventHandler<KeyEvent> tabListener = evt -> {
            if (evt.getCode() == KeyCode.TAB && !evt.isShiftDown()) {
                evt.consume();
                passageTextArea.requestFocus();
                passageTextArea.end();
            }
        };

 node.addEventHandler(KeyEvent.ANY, tabListener);
person jns    schedule 19.05.2016
comment
Спасибо за ваш ответ. Что, если пользователь использует клавишу Tab, чтобы переместить фокус с TextArea (например, с помощью Shift-Tab или Ctl-Tab на Mac)? Или что, если они используют Tab во время работы в TextArea, чтобы сделать отступ в абзаце, который они печатают? Будут ли эти ситуации также запускать этот Listener? - person skrilmps; 19.05.2016
comment
Поскольку вы не добавляете слушателя к TextArea, нажатие клавиши Tab, когда TextArea находится в фокусе, будет работать как обычно. Чтобы переместить фокус с TextArea, вы должны добавить isShiftDown в предложение if. - person jns; 19.05.2016

Вы можете просто использовать Platform.runLater(), чтобы переместить маркер в конец textArea. таким образом, он попадет в очередь задач пользовательского интерфейса и будет выполнен только после завершения события фокуса. вот как вы это делаете:

TextArea passageTextArea;

passageTextArea.focusedProperty().addListener((observable, oldValue, newValue) ->
{
    if(newValue)
    {
        Platform.runLater(() -> passageTextArea.end());
    }
});
person Tamir Croll    schedule 29.10.2019