【问题标题】:JavaFX-8: limit number of characters in a textfieldJavaFX-8:限制文本字段中的字符数
【发布时间】:2016-01-02 15:02:58
【问题描述】:

我正在尝试限制可以在 JavaFX-8 文本字段中插入的字符数:达到限制时会调用 endLineReached() 方法。 我想根据文本字段的大小(GUI 上的可见部分)设置最大字符数。所以我使用的代码是

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 的子项。

【问题讨论】:

  • 通常TextField 使用可变宽度字体,因此可见字符数取决于实际键入的字符。因此,我认为您所说的问题(“根据大小设置最大字符数”)格式不正确。你到底想做什么?防止文本水平滚动?
  • 是的,我试图阻止文本滚动。可能存在比处理 Textfield 中的字符数更好的方法来解决此问题:有没有办法在 TextField 上使用特定的侦听器?

标签: javafx javafx-8 textfield


【解决方案1】:

如果您想仅根据文本字段的视觉宽度来限制文本的长度,这有点棘手,因为它取决于许多因素(字体、文本字段的宽度、应用于文本字段,在可变宽度字体的情况下,已输入的实际文本等)。

注意这似乎是一件奇怪的事情(imo),因为如果碰巧使用窄字符,用户将能够输入相对较长的文本,但如果碰巧使用宽字符,用户将能够输入相对较短的文本(在下面的示例中我可以输入 26 个“l”,但只能输入 8 个“m”)。实际上,允许用户输入的文本应该基于逻辑考虑(即业务规则),而不是视觉考虑。但也许您对此有一些不寻常的用例。

您可以在文本字段上使用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);
    }
}

【讨论】:

  • 感谢您的 sn-p。我知道这种方法主要取决于文本字段中字符的字体、填充、宽度等。我的用例是一个提示shell(如Linux shell):当文本插入到达行尾时,插入的新字符必须写在新行中。 endLineReached() 方法在第一个文本字段下附加一个新文本字段作为 VBox 的子项。等等。所以我想知道是否有不同的更好的方法来解决这个问题......
  • 我认为对于那个用例,我会使用TextArea,将wrapText 设置为true,并且只是否决在最后一个换行符之前或跨越的任何修改。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-03-27
  • 1970-01-01
  • 2012-02-11
  • 1970-01-01
  • 2018-04-09
  • 1970-01-01
  • 2010-12-07
相关资源
最近更新 更多