如何使JavaFX TextField的宽度动态增长?

huangapple go评论93阅读模式
英文:

How do I have a javafx TextField width grow dynamically?

问题

这似乎是一个简单的问题,但我似乎找不到任何在线答案。我有一个带有一些初始化文本的TextField,并且我想找到一种在用户在文本框中输入时增加TextField宽度的方法。例如,使用这段代码:

  1. TextField iterations = new TextField("1000");
  2. iterations.setPrefWidth(50);

宽度是50,但如果用户在框中输入了"1000000",我希望宽度能动态调整到足够宽。是否有简单的解决方案,还是我需要像添加事件处理程序一样不断调整宽度这样过度复杂的方法?

英文:

This seems like a simple question, but I can't seem to find any online answers. I have a TextField with some initialized text within it, and I want to find a way to grow the TextField width as the user types in the box. For example, with this code:

  1. TextField iterations = new TextField("1000");
  2. iterations.setPrefWidth(50);

The width is 50, but if the user typed "1000000" into the box I'd want the width to dynamically adjust to be just wide enough. Is there a simple solution for this, or would I need to do something overkill like adding EventHandlers to constantly adjust the width?

答案1

得分: 3

最简单的方法是将列数绑定到文本长度,但它看起来不太精确,因为TextField使用其列数来考虑字体中最宽字符:

  1. iterations.prefColumnCountProperty().bind(
  2. Bindings.max(2, iterations.lengthProperty()));

(如果您只键入W字符,看起来还不错。)

一个更好看但更复杂的解决方案是使用TextField的皮肤来确定适当的大小:

  1. import javafx.application.Application;
  2. import javafx.application.Platform;
  3. import javafx.geometry.Insets;
  4. import javafx.stage.Stage;
  5. import javafx.scene.Scene;
  6. import javafx.scene.control.TextField;
  7. import javafx.scene.control.skin.TextFieldSkin;
  8. import javafx.scene.layout.HBox;
  9. public class GrowingTextField
  10. extends Application {
  11. private double margin = -1;
  12. private double minWidth = -1;
  13. @Override
  14. public void start(Stage stage) {
  15. TextField iterations = new TextField(" ");
  16. iterations.setPrefColumnCount(2);
  17. iterations.skinProperty().addListener((o, old, skin) -> {
  18. if (skin != null && margin < 0) {
  19. TextFieldSkin textFieldSkin = (TextFieldSkin) skin;
  20. Platform.runLater(() -> {
  21. margin = textFieldSkin.getCharacterBounds(0).getMinX();
  22. minWidth = iterations.prefWidth(0);
  23. Platform.runLater(() -> iterations.setText(""));
  24. });
  25. }
  26. });
  27. iterations.textProperty().addListener((o, oldText, text) -> {
  28. double width;
  29. if (text.length() <= iterations.getPrefColumnCount()) {
  30. width = minWidth;
  31. } else {
  32. TextFieldSkin skin = (TextFieldSkin) iterations.getSkin();
  33. double left = skin.getCharacterBounds(0).getMinX();
  34. double right = skin.getCharacterBounds(
  35. text.offsetByCodePoints(text.length(), -1)).getMaxX();
  36. width = right - left + margin * 2;
  37. }
  38. Platform.runLater(() -> iterations.setPrefWidth(width));
  39. });
  40. HBox pane = new HBox(iterations);
  41. pane.setPadding(new Insets(12));
  42. stage.setScene(new Scene(pane, 800, 150));
  43. stage.setTitle("Growing TextField");
  44. stage.show();
  45. }
  46. public static void main(String[] args) {
  47. launch(args);
  48. }
  49. }

我不明白为什么需要这样做。为什么不一开始就给TextField一个较大的列数,就像网页浏览器的URL字段一样?

英文:

The easiest approach is to bind the column count to the text length, but it won’t look very accurate, since a TextField uses its column count to account for the widest characters of the font:

  1. iterations.prefColumnCountProperty().bind(
  2. Bindings.max(2, iterations.lengthProperty()));

(Looks pretty good if you only type W characters.)

A better-looking, but more complicated, solution is to use the TextField’s skin to figure out the proper size:

  1. import javafx.application.Application;
  2. import javafx.application.Platform;
  3. import javafx.geometry.Insets;
  4. import javafx.stage.Stage;
  5. import javafx.scene.Scene;
  6. import javafx.scene.control.TextField;
  7. import javafx.scene.control.skin.TextFieldSkin;
  8. import javafx.scene.layout.HBox;
  9. public class GrowingTextField
  10. extends Application {
  11. private double margin = -1;
  12. private double minWidth = -1;
  13. @Override
  14. public void start(Stage stage) {
  15. TextField iterations = new TextField(&quot; &quot;);
  16. iterations.setPrefColumnCount(2);
  17. iterations.skinProperty().addListener((o, old, skin) -&gt; {
  18. if (skin != null &amp;&amp; margin &lt; 0) {
  19. TextFieldSkin textFieldSkin = (TextFieldSkin) skin;
  20. Platform.runLater(() -&gt; {
  21. margin = textFieldSkin.getCharacterBounds(0).getMinX();
  22. minWidth = iterations.prefWidth(0);
  23. Platform.runLater(() -&gt; iterations.setText(&quot;&quot;));
  24. });
  25. }
  26. });
  27. iterations.textProperty().addListener((o, oldText, text) -&gt; {
  28. double width;
  29. if (text.length() &lt;= iterations.getPrefColumnCount()) {
  30. width = minWidth;
  31. } else {
  32. TextFieldSkin skin = (TextFieldSkin) iterations.getSkin();
  33. double left = skin.getCharacterBounds(0).getMinX();
  34. double right = skin.getCharacterBounds(
  35. text.offsetByCodePoints(text.length(), -1)).getMaxX();
  36. width = right - left + margin * 2;
  37. }
  38. Platform.runLater(() -&gt; iterations.setPrefWidth(width));
  39. });
  40. HBox pane = new HBox(iterations);
  41. pane.setPadding(new Insets(12));
  42. stage.setScene(new Scene(pane, 800, 150));
  43. stage.setTitle(&quot;Growing TextField&quot;);
  44. stage.show();
  45. }
  46. public static void main(String[] args) {
  47. launch(args);
  48. }
  49. }

Output

如何使JavaFX TextField的宽度动态增长?


I do question why one would need this. Why not just give the TextField a large column count to start with, like a web browser’s URL field?

huangapple
  • 本文由 发表于 2023年5月24日 18:05:19
  • 转载请务必保留本文链接:https://go.coder-hub.com/76322343.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定