RichTextFX的撤消无法正常工作

时间:2018-07-23 19:11:54

标签: java javafx richtextfx

每当我在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();
    }
}

我想念什么吗?如果该bug存在,请问如何解决?

1 个答案:

答案 0 :(得分: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
        }
    }
}
相关问题