JavaFX-8 使文本插入符号在只读文本区域中可见



JavaFX 文本字段如果设置为只读模式,则不会显示文本插入符号。下面是一个示例:

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.TextArea;
import javafx.stage.Stage;
public class TextAreaReadOnly extends Application {
    public TextAreaReadOnly() {
    }
    @Override
    public void start(Stage primaryStage) throws Exception {
        TextArea textarea = new TextArea();
        textarea.setText("This is allnreadonly textnin here.");
        textarea.setEditable(false);
        Scene scene = new Scene(textarea, 600, 400);
        primaryStage.setScene(scene);
        primaryStage.show();
    }    
    public static void main(String[] args) {
        launch(args);
    }
}

虽然仍然可以使用 Shift+光标键选择文本,但不显示插入符号。有谁知道解决这个问题的方法?

在Neil的回答触发下,我尝试快速测试我的建议,以扩展TextAreaSkin并将caretVisible属性替换为不检查可编辑性的属性。似乎有效(虽然没有经过彻底测试) - 但需要反射访问超级的私人眨眼属性。显然很脏,在安全受限的情况下是不可能的......

public static class MyTextAreaSkin extends TextAreaSkin {
    public MyTextAreaSkin(TextArea textInput) {
        super(textInput);
        caretVisible = new BooleanBinding() {
            { bind(textInput.focusedProperty(), textInput.anchorProperty(), 
                    textInput.caretPositionProperty(),
                    textInput.disabledProperty(), displayCaret , blinkProperty() );}
            @Override protected boolean computeValue() {
                return !blinkProperty().get() &&  displayCaret.get() && textInput.isFocused() &&
                        (isWindows() || (textInput.getCaretPosition() == textInput.getAnchor())) 
                        && !textInput.isDisabled(); 
            }
        };
        // rebind opacity to replaced caretVisible property
        caretPath.opacityProperty().bind(new DoubleBinding() {
            { bind(caretVisible); }
            @Override protected double computeValue() {
                return caretVisible.get() ? 1.0 : 0.0;
            }
        });
    }
    BooleanProperty blinkAlias;
    BooleanProperty blinkProperty() {
        if (blinkAlias == null) {
            Class<?> clazz = TextInputControlSkin.class;
            try {
                Field field = clazz.getDeclaredField("blink");
                field.setAccessible(true);
                blinkAlias = (BooleanProperty) field.get(this);
            } catch (NoSuchFieldException | SecurityException 
                   | IllegalArgumentException | IllegalAccessException e) {
                // TBD: errorhandling
                e.printStackTrace();
            }
        }
        return blinkAlias;
    }
}
// usage in a custom TextArea
TextArea textarea = new TextArea() {
    @Override
    protected Skin<?> createDefaultSkin() {
        return new MyTextAreaSkin(this);
    }
};

我想要同样的东西 - 一个只读字段,但插入符号可用于导航。 我试过了:

.text-input:readonly { -fx-display-caret: true; }

但无济于事。 深入研究 FX 源代码(对于 2.2),我发现:

caretVisible = new BooleanBinding() {
        { bind(textInput.focusedProperty(), textInput.anchorProperty(), textInput.caretPositionProperty(),
                textInput.disabledProperty(), textInput.editableProperty(), displayCaret, blink);}
        @Override protected boolean computeValue() {
            // RT-10682: On Windows, we show the caret during selection, but on others we hide it
            return !blink.get() && displayCaret.get() && textInput.isFocused() &&
                    (isWindows() || (textInput.getCaretPosition() == textInput.getAnchor())) &&
                    !textInput.isDisabled() &&
                    textInput.isEditable();
        }
    };

看起来没有办法在该条件的末尾覆盖要求 isEditable()。 我可能会在虚拟插入符号上绘画作为解决方法,这很丑陋,但我不确定还有另一种方法 - 看起来您可以伪造插入符号或伪造只读方面(拒绝对控件的所有编辑)。

最新更新