我需要在JavaFX 2.1中动态创建窗格上的矩形.接下来我需要在Rectangle上居中/包装/截断Text.文本必须适合矩形.我能够使用以下代码对文本进行居中和包装,但是,如果文本长度太长,它将显示在矩形之外.我想在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);
Run Code Online (Sandbox Code Playgroud)
我可以使用哪些属性来实现这一目标,还是有更好的方法来实现这一目标?
这是一个示例替代实现.
它使用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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
示例应用的示例输出:

几个笔记:
通常最好使用a Label而不是尝试重新创建Label的一部分功能.
方法中的布局layoutChildren类似于JavaFX团队在实现JavaFX控件库时使用的布局.可能是他们使用layoutChildren而不是绑定布局的原因,但我不知道所有这些原因是什么.
我找到了简单的布局,使用JavaFX库中的预构建控件和布局管理器是最好的(例如,上面的控件可能只使用StackPane中的Label或Text实现).我无法从内置布局获得我需要的布局,然后我将使用绑定来补充它们的使用,我发现它也很容易使用.我不需要layoutChildren那么多使用.这可能只是扩展到布局复杂节点组的问题 - 最有可能在layoutChildren方法中进行计算表现更好,并且在应用于复杂节点组时可能更容易使用和调试.
而不是截断Text通过从计算文本大小和eliding多余的字符String作为一个Label做,代码改为调用setClip文本节点直观地把它夹到矩形的大小上.如果您希望截断Text更像a Label,那么您可以查看JavaFX实用程序类的代码,该类用于计算剪切文本.
问题中的示例代码无法编译,因为它缺少wrappingWidthProperty表达式上的括号,并且它在绑定表达式中使用getValue和getWidth方法,这是不可能的 - 相反,它需要使用侦听器boundsInLocalProperty.
此外,创建了一个小型示例应用程序演示,将放置在带有矩形背景的Label中的文本添加到窗格,通过绑定精确控制标记矩形的x,y位置.