【问题标题】:How to center/wrap/truncate Text to fit within Rectangle in JavaFX 2.1?如何在 JavaFX 2.1 中将文本居中/换行/截断以适合矩形?
【发布时间】:2012-05-24 14:21:39
【问题描述】:

我需要在 JavaFX 2.1 中通过窗格动态创建矩形。接下来我需要在矩形上居中/换行/截断文本。文本必须适合矩形。我可以使用以下代码将文本居中并换行,但是,如果文本长度太长,它将出现在矩形之外。我想在 StackPane 中创建类似于 Label 的行为,本质上,如果 Rectangle 增长,Text 会随之增长,但始终保持在 Rectangle 的中心,如果 Text 不能放入 Rectangle 中,它将被相应地截断。

Rectangle r;

Text t;

...

//center and wrap text within rectangle

t.wrappingWidthProperty().bind(rect.widthProperty().multiply(0.9);

t.xProperty().bind(rect.xProperty().add(rect.widthProperty().subtract(t.boundsInLocalProperty().getValue().getWidth().divide(2)));

t.yProperty().bind(rect.yProperty().add(rect.heightProperty().divide(2)));

t.setTextAlignment(TextAlignment.CENTER);

t.setTextOrigin(VPos.CENTER);

我可以使用哪些属性来实现这一点,或者有更好的方法吗?

【问题讨论】:

  • 为什么不直接使用带有背景颜色的标签?

标签: javafx javafx-2


【解决方案1】:

这是一个示例替代实现。

它使用Group 的子类和layoutChildren 实现而不是绑定api。

import javafx.application.Application;
import javafx.beans.property.StringProperty;
import javafx.geometry.VPos;
import javafx.scene.*;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.*;
import javafx.stage.Stage;

public class TextInRectangle extends Application {
  public static void main(String[] args) throws Exception { launch(args); }
  public void start(final Stage stage) throws Exception {
    TextBox text = new TextBox("All roads lead to Rome", 100, 100);
    text.setLayoutX(30);
    text.setLayoutY(20);
    final Scene scene = new Scene(text, 160, 140, Color.CORNSILK);
    stage.setScene(scene);
    stage.show();
  }

  class TextBox extends Group {
    private Text text;
    private Rectangle rectangle;
    private Rectangle clip;
    public StringProperty textProperty() { return text.textProperty(); }

    TextBox(String string, double width, double height) {
      this.text = new Text(string);
      text.setTextAlignment(TextAlignment.CENTER);
      text.setFill(Color.FORESTGREEN);
      text.setTextOrigin(VPos.CENTER);
      text.setFont(Font.font("Comic Sans MS", 25));
      text.setFontSmoothingType(FontSmoothingType.LCD);

      this.rectangle = new Rectangle(width, height);
      rectangle.setFill(Color.BLACK);

      this.clip = new Rectangle(width, height);
      text.setClip(clip);

      this.getChildren().addAll(rectangle, text);
    }

    @Override protected void layoutChildren() {
      final double w = rectangle.getWidth();
      final double h = rectangle.getHeight();
      clip.setWidth(w);
      clip.setHeight(h);
      clip.setLayoutX(0);
      clip.setLayoutY(-h/2);

      text.setWrappingWidth(w * 0.9);
      text.setLayoutX(w / 2 - text.getLayoutBounds().getWidth() / 2);
      text.setLayoutY(h / 2);
    }
  }
}

示例应用的示例输出:

几点说明:

  1. 通常最好使用Label,而不是尝试重新创建标签的部分功能。

  2. layoutChildren 方法中的布局类似于 JavaFX 团队在实现 JavaFX 控件库时使用的布局。他们使用layoutChildren 而不是绑定布局可能是有原因的,但我不知道所有这些原因是什么。

  3. 我发现对于简单的布局,最好使用 JavaFX 库中的预构建控件和布局管理器(例如,上述控件可以仅使用 StackPane 中的标签或文本来实现)。如果我无法从内置布局中获得所需的布局,那么我将使用绑定来补充它们的使用,我发现它也很容易使用。我不需要那么多使用layoutChildren。这可能只是扩展以布置复杂节点组的问题 - 最有可能在 layoutChildren 方法中进行计算会表现得更好,并且在应用于复杂节点组时可能更容易使用和调试。

    李>
  4. 代码不是像 Label 那样通过计算文本大小并从 String 中删除多余字符来截断 Text,而是在文本节点上调用 setClip 以直观地将其剪辑到矩形的大小。相反,如果您希望截断 Text 更像是 Label,那么您可以查看用于计算剪切文本的 JavaFX utility class 的代码。

  5. 问题中的示例代码无法编译,因为它在 wrappingWidthProperty 表达式上缺少括号,并且它在绑定表达式中使用 getValuegetWidth 方法,这是不可能的 - 而是它需要在boundsInLocalProperty 上使用监听器。

另外,创建了一个small sample app 演示,将放置在具有矩形背景的标签中的文本添加到窗格中,并通过绑定精确控制标记矩形的 x、y 位置。

【讨论】:

  • 在正常情况下,我很乐意使用 Label 或现有布局类和 Label 的组合来执行此操作,但我需要精确控制标记的 Rectangle 的 x,y 位置,以便绑定矩形到基本窗格就可以了。我希望我可以对 Text 类做同样的事情,使用属性 API 将它绑定到 Rectangle。显示的文本绑定代码实际上是在 Rectangle 宽度属性更改时在侦听器方法中调用...我将研究使用 Group。谢谢大家的评论。
  • 更新了答案以引用一个演示基于绑定的方法的小示例应用程序。
  • jewelsea,感谢您花时间分享如此精美的代码。我现在改用Label了。
猜你喜欢
  • 2013-07-07
  • 1970-01-01
  • 2021-09-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多