2014-12-04 86 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