2016-01-02 82 views
0

我試圖限制可插入到JavaFX-8 TextField中的字符數:達到限制時endLineReached()方法被調用。 我想根據文本字段的大小(GUI上的可見部分)設置最大字符數。所以,我正在使用的代碼是JavaFX-8:文本字段中的字符數限制

textfield.textProperty().addListener((ov, oldValue, newValue) -> { 
      onEndLine(textfield.getText(), textfield.getPrefColumnCount()); 
     }); 


public void onEndLine(String text, int prefColumnCount) { 
    if (text.length() > prefColumnCount) { 
     endLineReached(); 
    } 
} 

的問題是,textfield.getPrefColumnCount()無法正常工作。此外,我無法以編程方式設置prefColumnCount值,因爲每次程序重新啓動時(不是在執行期間),文本字段的寬度都可能會發生變化。該文本字段是JavaFX HBox的子項。

+0

通常'TextField'使用可變寬字體,所以可見字符的數量取決於實際鍵入的字符數。所以我不認爲你說過的問題(「根據大小設置最大字符數」)是格式良好的。你究竟在做什麼?防止文本水平滾動? –

+0

是的,我試圖阻止文本滾動。可能存在一個更好的方法來解決這個問題,而不是處理文本字段中的字符數:有沒有辦法在TextField上使用特定的偵聽器? – Squerut

回答

0

如果您想要僅基於文本字段的可視寬度來限制文本的長度,這有點棘手,因爲它取決於許多因素(字體,文本字段的寬度,應用於填充的填充文本字段,在可變寬度字體的情況下,輸入的實際文本等)。

注意這看起來很奇怪(imo),因爲如果碰巧使用窄字符,用戶將能夠輸入相對較長的文本,但如果碰巧使用寬字符,則會輸入相對較短的文本(在本例中下面我可以輸入26「l」s但只有8「m」s)。真正允許用戶輸入的文本應該基於邏輯考慮(即業務規則),而不是視覺上的考慮。但是,也許你有一些不尋常的用例。

您可以在文本字段上使用text formatter來否決添加文本。要檢查寬度,請使用新文本創建一個新的Text對象,將字體設置爲與文本字段相同的字體,然後檢查其寬度。您還需要在文本字段中說明填充。請注意,這有點脆弱,因爲您並不真正瞭解文本字段佈局的實現情況,但至少在JDK版本中,這看起來工作正常。

import javafx.application.Application; 
import javafx.geometry.Insets; 
import javafx.geometry.Pos; 
import javafx.scene.Scene; 
import javafx.scene.control.TextField; 
import javafx.scene.control.TextFormatter; 
import javafx.scene.control.TextInputControl; 
import javafx.scene.layout.VBox; 
import javafx.scene.text.Text; 
import javafx.stage.Stage; 

public class TextFieldNoScroll extends Application { 

    @Override 
    public void start(Stage primaryStage) { 
     TextField textField = new TextField(); 
     textField.setTextFormatter(new TextFormatter<String>(change -> { 

      if (change.isAdded()) { 
       Insets textFieldInsets = change.getControl().getPadding();    
       double horizPadding = textFieldInsets.getLeft() + textFieldInsets.getRight() ; 

       Text newText = new Text(change.getControlNewText()); 
       newText.setFont(((TextInputControl)change.getControl()).getFont()); 
       double newTextWidth = newText.getBoundsInLocal().getWidth(); 
       if (newTextWidth + horizPadding > change.getControl().getWidth()) { 
        return null ; 
       } 
      } 

      return change ; 
     })); 

     VBox root = new VBox(textField); 
     root.setAlignment(Pos.CENTER); 
     Scene scene = new Scene(root, 120, 120); 
     primaryStage.setScene(scene); 
     primaryStage.show(); 
    } 


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

謝謝你的片段。我知道這種方法主要取決於文本字段中charchters的字體,填充,寬度等。 我使用的用例是一個提示shell(如Linux shell):當文本插入到達行尾時,插入的新字符必須以新行寫入。 _endLineReached()_方法將第一個文本字段添加爲VBox的子項。等等。 所以我想知道是否有不同的更好的方法來解決這個問題... – Squerut

+0

我認爲這種用例我會使用'TextArea','wrapText'設置爲'true',並且只是否決最後換行符之前或跨越的任何修改。 –