Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javafx textfield resize to text length?

Hello guys I am building a chat server where I use a textfield on the screen to type in the chat message that the user writes, the idea is that it works like a bubble over a persons head when he types a message.

my question is in order to not make a textbox that is too large or too small is there a way to make the textbox resize (trim if you will) so it adjust to the text written in the textfield?

P.S. I'm using JavaFx scenebuilder to do all of this.

like image 869
Marc Rasmussen Avatar asked Oct 05 '12 00:10

Marc Rasmussen


3 Answers

You can use computeTextWidth method in the com.sun.javafx.scene.control.skin.Utils. the method is used in javafx.scene.control.Label class to calculate the minimum width for label content.

I solved my problem as below:

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);
        }
    });

I have added a listener to textProperty, and with every text change i change the prefWidth of textfield.

Note: as long as the Utils.computeTextWidth() is not public, I have copied the source code to a new class (TextUtils).

Here is the full source code:

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;
    }
}
like image 160
2 revs, 2 users 79% Avatar answered Sep 17 '22 14:09

2 revs, 2 users 79%


In JavaFX 8, there is a solution for that, here is the code:

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!");
  • In JavaFX 2.2 this code works with little limitations. You can't set the Font(so if you do not use the std-font, you must set it manually).
  • You can't get the padding from a TextField(so if you know the padding, write it hardcoded).

Happy Coding,
Kalasch

like image 27
Kalaschni Avatar answered Sep 19 '22 14:09

Kalaschni


Since JavaFX 8, this is by far the simplest:

textField.prefColumnCountProperty().bind(textField.textProperty().length());
like image 29
Emily L. Avatar answered Sep 19 '22 14:09

Emily L.