【问题标题】:Javafx textfield resize to text length?Javafx文本字段调整为文本长度?
【发布时间】:2012-09-26 02:42:16
【问题描述】:

大家好,我正在构建一个聊天服务器,在其中我使用屏幕上的文本字段来输入用户编写的聊天消息,其想法是当他输入消息时它就像一个人头上的气泡一样工作。

我的问题是为了不让文本框太大或太小,有没有办法让文本框调整大小(如果你愿意,可以修剪),使其适应文本字段中写入的文本?

附:我正在使用 JavaFx scenebuilder 来完成所有这些工作。

【问题讨论】:

    标签: user-interface javafx textfield


    【解决方案1】:

    是时候在幕后进行一些编码了(builder) :)。
    以下代码块不是一个简洁的解决方案,但总比没有好。 :)

    // define width limits
    textField.setMinWidth(50);
    textField.setPrefWidth(50);
    textField.setMaxWidth(400);
    // add listner
    textField.textProperty().addListener(new ChangeListener<String>() {
        @Override
        public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
            textField.setPrefWidth(textField.getText().length() * 7); // why 7? Totally trial number.
        }
    });
    

    【讨论】:

    • 首先... NICE WORK 2nd 你能详细解释一下它的作用吗?! :)
    • 这假设存在的每个 javafx 字体的每个字符在任何情况下都是 7px 宽……这可能只是人类历史上最糟糕的假设。这就像用(巨大的)软管的水压飞入太空。
    • 嘿@specializt 这还不错。如果您的应用程序中没有其他用例,则此假设可能会节省很多天;)。否则,您可能总是在此处或类似问题上评估其他答案,如果这些答案不令人满意,当然可以发布您的答案。除此之外,我将尝试使用更新的选项更新答案,自发布以来已有很多改进。谢谢提醒。
    • 数字 7 对我有用,你在说什么 @specializt?
    • @DonLarynx 正是我写的。写得再简单不过了……也许你应该向会说英语的人寻求帮助。
    【解决方案2】:

    您可以在com.sun.javafx.scene.control.skin.Utils 中使用computeTextWidth 方法。该方法在javafx.scene.control.Label类中用于计算标签内容的最小宽度。

    我解决了我的问题如下:

    field.textProperty().addListener(new ChangeListener<String>() {
            @Override
            public void changed(ObservableValue<? extends String> ob, String o,
                    String n) {
                // expand the textfield
                field.setPrefWidth(TextUtils.computeTextWidth(field.getFont(),
                        field.getText(), 0.0D) + 10);
            }
        });
    

    我已向textProperty 添加了一个监听器,并且每次更改文本时,我都会更改文本字段的prefWidth

    注意:只要Utils.computeTextWidth()不公开,我已将源代码复制到一个新类(TextUtils)。

    这里是完整的源代码:

    package me.jone30rw.fxcontrol;
    
    import javafx.scene.text.Font;
    import javafx.scene.text.Text;
    import javafx.scene.text.TextBoundsType;
    
    public class TextUtils {
    
        static final Text helper;
        static final double DEFAULT_WRAPPING_WIDTH;
        static final double DEFAULT_LINE_SPACING;
        static final String DEFAULT_TEXT;
        static final TextBoundsType DEFAULT_BOUNDS_TYPE;
        static {
            helper = new Text();
            DEFAULT_WRAPPING_WIDTH = helper.getWrappingWidth();
            DEFAULT_LINE_SPACING = helper.getLineSpacing();
            DEFAULT_TEXT = helper.getText();
            DEFAULT_BOUNDS_TYPE = helper.getBoundsType();
        }
    
        public static double computeTextWidth(Font font, String text, double help0) {
            // Toolkit.getToolkit().getFontLoader().computeStringWidth(field.getText(),
            // field.getFont());
    
            helper.setText(text);
            helper.setFont(font);
    
            helper.setWrappingWidth(0.0D);
            helper.setLineSpacing(0.0D);
            double d = Math.min(helper.prefWidth(-1.0D), help0);
            helper.setWrappingWidth((int) Math.ceil(d));
            d = Math.ceil(helper.getLayoutBounds().getWidth());
    
            helper.setWrappingWidth(DEFAULT_WRAPPING_WIDTH);
            helper.setLineSpacing(DEFAULT_LINE_SPACING);
            helper.setText(DEFAULT_TEXT);
            return d;
        }
    }
    

    【讨论】:

    • 是否可以通过实际创建标签以某种方式使用 computeTextWidth()?我尝试使用文本创建标签,然后使用 getMinWidth() 和 widthProperty().doubleValue(),但两者总是返回 0.0...
    • 很好的解决方案!
    【解决方案3】:

    在 JavaFX 8 中,有一个解决方案,代码如下:

    TextField tf = new TextField();
    // Set Max and Min Width to PREF_SIZE so that the TextField is always PREF
    tf.setMinWidth(Region.USE_PREF_SIZE);
    tf.setMaxWidth(Region.USE_PREF_SIZE);
    tf.textProperty().addListener((ov, prevText, currText) -> {
        // Do this in a Platform.runLater because of Textfield has no padding at first time and so on
        Platform.runLater(() -> {
            Text text = new Text(currText);
            text.setFont(tf.getFont()); // Set the same font, so the size is the same
            double width = text.getLayoutBounds().getWidth() // This big is the Text in the TextField
                    + tf.getPadding().getLeft() + tf.getPadding().getRight() // Add the padding of the TextField
                    + 2d; // Add some spacing
            tf.setPrefWidth(width); // Set the width
            tf.positionCaret(tf.getCaretPosition()); // If you remove this line, it flashes a little bit
        });
    });
    tf.setText("Hello World!");
    
    • 在 JavaFX 2.2 中,此代码几乎没有限制。您无法设置字体(因此,如果您不使用标准字体,则必须手动设置)。
    • 您无法从 TextField 中获取填充(因此,如果您知道填充,请将其写入硬编码)。

    快乐编码,
    卡拉什

    【讨论】:

    • 这对我来说是最好的答案。这个答案并没有在实际单词的右侧留下很多空间。不过我确实必须做tf.setPrefWidth(width + 14)
    【解决方案4】:

    如果您使用 setPrefColumnCount,则不需要依赖字体的魔法

            tf.textProperty().addListener(new ChangeListener<String>() {
                @Override
                public void changed(ObservableValue<? extends String> ob, String o, String n) {
                    tf.setPrefColumnCount(tf.getText().length() +1);
                }
            });
    

    【讨论】:

      【解决方案5】:

      自 JavaFX 8 以来,这是迄今为止最简单的:

      textField.prefColumnCountProperty().bind(textField.textProperty().length());
      

      【讨论】:

      • 请注意,这不适用于可变宽度字体(这很可能是典型 TextField 的默认设置)。 JavaFX 似乎根据最宽字符 ('W') 的宽度计算首选项宽度,这高估了实际输入文本的长度。
      • 那行不通。
      【解决方案6】:

      最好/最简单的方法是使用 JavaFX 的“USE_COMPUTED_SIZE”选项。您可以在 FXML 中定义它,也可以像这样以编程方式定义它:

      TextField textField = new TextField("hello");
      textField.setPrefWidth(Control.USE_COMPUTED_SIZE);
      

      【讨论】:

        猜你喜欢
        • 2013-02-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-09-14
        • 2015-01-16
        • 1970-01-01
        相关资源
        最近更新 更多