How to prevent JScrollPane arrow key handling from moving caret when Scroll Pane wraps Text Pane

喜夏-厌秋 提交于 2019-12-19 11:54:31

问题


I have the following requirements:

I need a scrollable JTextPane. The user may type into this text pane, or text may be inserted into it that is not typed by the user. Think something like an IM window. Although the window must be scrollable to allow the user to review text previously typed, the caret should never move from its position at the end of the text. Any text entered by the user will always appear at the end.

In JTextPane, when the user scrolls with the scroll bar, the caret does not move. The viewport is adjusted. However, when the user presses the up and down arrow keys, the JTextPane caret moves with it (whether the window scrolls or not).

What I want is that an up arrow key would function the same as moving the scroll bar up with the mouse. The arrow keys should have nothing to do with the caret.

I have tried the following approaches, without success: 1) add a "No-op" action to the Keymap for my text pane class (using JTextPane.addKeymap() and Keymap.addActionForKeyStroke()). This stops the caret from moving but prevents the action from being passed on to the Scroll Pane to scroll the view. 2) remove the arrow keys from the keymap for my text pane class. This affects all JTextPanes in my application which is not what I want.

What I want is to add an action to my TextPane keymap that simply calls the ScrollPane action for Up and Down arrow.

What is the best way to accomplish this?

A possibility that occurs to me is to implement a KeyListener (which receives the key stroke before the keymap) to trap these keys and then to implement the scrolling by hand. But this would seem to require me to compute font sizes, etc. Is there an easier way?

The ideal thing would be if there was some way to "anchor" the caret to whatever the end of the text was.


回答1:


You're going to have to modify the KeyBindings

Try this to start with

InputMap im = textArea.getInputMap(WHEN_FOCUSED);
ActionMap am = textArea.getActionMap();

am.get("caret-down").setEnabled(false);
am.get("caret-up").setEnabled(false);

Now that you have that working, you need to worry about all these

selection-up = shift pressed UP
caret-next-word = ctrl pressed RIGHT
selection-previous-word = shift ctrl pressed LEFT
selection-up = shift pressed KP_UP
caret-down = pressed DOWN
caret-previous-word = ctrl pressed LEFT
caret-end-line = pressed END
selection-page-up = shift pressed PAGE_UP
caret-up = pressed KP_UP
delete-next = pressed DELETE
caret-begin = ctrl pressed HOME
selection-backward = shift pressed LEFT
caret-end = ctrl pressed END
delete-previous = pressed BACK_SPACE
selection-next-word = shift ctrl pressed RIGHT
caret-backward = pressed LEFT
caret-backward = pressed KP_LEFT
selection-forward = shift pressed KP_RIGHT
delete-previous = ctrl pressed H
unselect = ctrl pressed BACK_SLASH
insert-break = pressed ENTER
selection-begin-line = shift pressed HOME
caret-forward = pressed RIGHT
selection-page-left = shift ctrl pressed PAGE_UP
selection-down = shift pressed DOWN
page-down = pressed PAGE_DOWN
delete-previous-word = ctrl pressed BACK_SPACE
delete-next-word = ctrl pressed DELETE
selection-backward = shift pressed KP_LEFT
selection-page-right = shift ctrl pressed PAGE_DOWN
caret-next-word = ctrl pressed KP_RIGHT
selection-end-line = shift pressed END
caret-previous-word = ctrl pressed KP_LEFT
caret-begin-line = pressed HOME
caret-down = pressed KP_DOWN
selection-forward = shift pressed RIGHT
selection-end = shift ctrl pressed END
selection-previous-word = shift ctrl pressed KP_LEFT
selection-down = shift pressed KP_DOWN
insert-tab = pressed TAB
caret-up = pressed UP
selection-begin = shift ctrl pressed HOME
selection-page-down = shift pressed PAGE_DOWN
delete-previous = shift pressed BACK_SPACE
caret-forward = pressed KP_RIGHT
selection-next-word = shift ctrl pressed KP_RIGHT
page-up = pressed PAGE_UP



回答2:


What if you let user place caret e.g. to let him select and copy some text?

I would add a DocumentFilter (or override insertString() method of the Document) and in all cases perform insert in the doc.getLength() position and resetting the caret to the doc.getLength() position after the insert.



来源:https://stackoverflow.com/questions/12041277/how-to-prevent-jscrollpane-arrow-key-handling-from-moving-caret-when-scroll-pane

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!