2014-12-04 92 views
3

如果将它们设置为只读模式,则JavaFX文本字段不显示文本插入符号。下面是一个示例:JavaFX-8使文本插入符在只读文本区域中可见

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 all\nreadonly text\nin 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 +光标键选择文本,但不会显示插入符号。有没有人知道这个解决方法?

+0

为什么在'ReadOnly'文本控件上需要'TextCaret'?当它悬停在文本上时,是否要设置鼠标指针的样式? – ItachiUchiha 2014-12-04 10:46:57

+0

我不想让鼠标指针改变。我希望textarea显示TextInputControl.getCaretPosition()的位置。 我猜TextArea背后没有显示插入符号的基本原理是你不需要它,因为无论如何,只要它是只读的,你都不能插入任何文本。但这是错误的(IMO),因为你仍然可以用光标键选择文本,因此你绝对需要一个插入符号。 – rli 2014-12-04 10:53:13

回答

3

Neil's answer触发,我试着对我的建议进行快速测试,以扩展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); 
    } 

}; 
2

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

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

但无济于事。挖掘到FX source code (for 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()。我可能会在假人身上涂上一张假脱胎纸,这很丑陋,但我不确定是否有另一种方法 - 看起来你可以伪造脱字符或伪造只读方面(拒绝所有对控件的编辑)。

+0

加上一个挖掘:-)你可能会考虑实现一个自定义皮肤,并重写绑定 - caretVisible是受保护的(虽然眨眼不是),只用于caretPath,它也受保护,所以你可以逃避延长.. – kleopatra 2015-01-12 13:02:50

+0

如果您不在安全限制的环境中(并且公司规则允许):自定义[TextAreaSkin](http://stackoverflow.com/a/27904371/203657)似乎可以做到这一点。虽然没有测试过副作用 – kleopatra 2015-01-12 14:38:47