1

每当我在 CodeArea 中键入内容并按 CTRL + Z 然后再次开始键入时,光标就会重置到文本的开头。

我调查了这个问题https://github.com/FXMisc/RichTextFX/issues/761并且似乎这个错误已修复。但是,我能够在最新版本(0.9.1)中复制该错误。

以下代码将复制该行为:

public class GuiTest extends Application {

    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        StyleClassedTextArea  codeArea = new StyleClassedTextArea();
        codeArea.replaceText("Text");

        VirtualizedScrollPane<StyleClassedTextArea> scrollPane = new VirtualizedScrollPane<>(codeArea);

        final Scene scene = new Scene(scrollPane, 600, 400);
        primaryStage.setScene(scene);
        primaryStage.show();
    }
}

我错过了什么吗?如果错误存在任何想法如何解决它?

4

1 回答 1

0

经过简短的调试后,我发现 RichTextFx 在选择新范围时会出现一些奇怪的行为(从这个范围开始输入文本,光标位置无关紧要)。选择新范围时,当前范围设置为 0,0,然后仅移动到光标位置。但是,在执行撤消后,新范围被选择为 0,0 而永远不会选择到当前光标位置。这是因为当我们按下 undo 时,虽然光标在另一个位置突出显示,但文本从 0,0 开始输入。

我能够使用反射在一定程度上解决这个问题。您需要扩展StyleClassedTextArea,覆盖该undo()方法,执行撤消,然后设置您需要范围的位置。您可以将范围设置为当前光标位置,但光标并不总是在正确的位置,尤其是当光标需要时移动到另一个段落中的另一个样式。我在 undoManager 的 ChangeQueue 中得到了正确的位置范围。

您需要确保正确投射,所以在投射之前进行一些调试。

@Override
public void undo() {
    if (isUndoAvailable()) {
        super.undo();
        UndoManager undoManager = getUndoManager();
        try {
            Field queueField = UndoManagerImpl.class.getDeclaredField("queue");
            queueField.setAccessible(true);
            UnlimitedChangeQueue queue = (UnlimitedChangeQueue) queueField
                    .get(undoManager);
            int newRange = ((PlainTextChange) ((List) queue.peekNext()).get(0))
                    .getRemovalEnd();
            selectRange(newRange, newRange);
        } catch (NoSuchFieldException | IllegalAccessException e) {
            // Handle exception
        }
    }
}

@Override
public void redo() {
    if (isRedoAvailable()) {
        super.redo();
        UndoManager undoManager = getUndoManager();
        try {
            Field queueField = UndoManagerImpl.class.getDeclaredField("queue");
            queueField.setAccessible(true);
            UnlimitedChangeQueue queue = (UnlimitedChangeQueue) queueField
                    .get(undoManager);
            int newRange = ((PlainTextChange) ((List) queue.peekPrev()).get(0))
                    .getInsertionEnd();
            selectRange(newRange, newRange);
        } catch (NoSuchFieldException | IllegalAccessException e) {
            // Handle
        }
    }
}
于 2018-07-29T03:26:42.547 回答