2016-01-02 85 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',并且只是否决最后换行符之前或跨越的任何修改。 –