【发布时间】:2012-09-26 02:42:16
【问题描述】:
大家好,我正在构建一个聊天服务器,在其中我使用屏幕上的文本字段来输入用户编写的聊天消息,其想法是当他输入消息时它就像一个人头上的气泡一样工作。
我的问题是为了不让文本框太大或太小,有没有办法让文本框调整大小(如果你愿意,可以修剪),使其适应文本字段中写入的文本?
附:我正在使用 JavaFx scenebuilder 来完成所有这些工作。
【问题讨论】:
标签: user-interface javafx textfield
大家好,我正在构建一个聊天服务器,在其中我使用屏幕上的文本字段来输入用户编写的聊天消息,其想法是当他输入消息时它就像一个人头上的气泡一样工作。
我的问题是为了不让文本框太大或太小,有没有办法让文本框调整大小(如果你愿意,可以修剪),使其适应文本字段中写入的文本?
附:我正在使用 JavaFx scenebuilder 来完成所有这些工作。
【问题讨论】:
标签: user-interface javafx textfield
是时候在幕后进行一些编码了(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.
}
});
【讨论】:
您可以在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;
}
}
【讨论】:
在 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!");
快乐编码,
卡拉什
【讨论】:
tf.setPrefWidth(width + 14)。
如果您使用 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);
}
});
【讨论】:
自 JavaFX 8 以来,这是迄今为止最简单的:
textField.prefColumnCountProperty().bind(textField.textProperty().length());
【讨论】:
最好/最简单的方法是使用 JavaFX 的“USE_COMPUTED_SIZE”选项。您可以在 FXML 中定义它,也可以像这样以编程方式定义它:
TextField textField = new TextField("hello");
textField.setPrefWidth(Control.USE_COMPUTED_SIZE);
【讨论】: