Java 包含包裹标签的对照皮肤的首选高度

Java 包含包裹标签的对照皮肤的首选高度,java,javafx,label,javafx-8,word-wrap,Java,Javafx,Label,Javafx 8,Word Wrap,我写了一个基本控件和它的皮肤。皮肤中的HBox中显示标签。如果没有足够的空间,此标签应包装其文本 public class LabelWrap extends Application { public static void main(String[] args) { launch(LabelWrap.class); } @Override public void start(Stage stage) throws Exception {

我写了一个基本控件和它的皮肤。皮肤中的
HBox
中显示
标签。如果没有足够的空间,此标签应包装其文本

public class LabelWrap extends Application {

    public static void main(String[] args) {
        launch(LabelWrap.class);
    }

    @Override
    public void start(Stage stage) throws Exception {
        BasicControl basicControl = new BasicControl();
        BorderPane borderPane = new BorderPane();
        borderPane.setPrefWidth(150);
        borderPane.setCenter(basicControl);

        stage.setScene(new Scene(borderPane));
        stage.centerOnScreen();
        stage.show();
    }

    private static class BasicControl extends Control {
        @Override
        protected Skin<?> createDefaultSkin() {
            return new BasicControlSkin(this);
        }
    }

    private static class BasicControlSkin extends SkinBase<BasicControl> {
        protected BasicControlSkin(BasicControl control) {
            super(control);
            VBox box = new VBox();
            Label label = new Label("This text should wrap because it is too long");
            label.setWrapText(true);
            box.getChildren().add(label);
            getChildren().add(box);
        }
    }
}
public类LabelWrap扩展了应用程序{
公共静态void main(字符串[]args){
发布(LabelWrap.class);
}
@凌驾
public void start(Stage)引发异常{
BasicControl BasicControl=新的BasicControl();
BorderPane BorderPane=新的BorderPane();
borderPane.setPrefWidth(150);
边框窗格。设置中心(基本控件);
舞台场景(新场景(边框));
stage.centerOnScreen();
stage.show();
}
私有静态类BasicControl扩展了控件{
@凌驾
受保护的皮肤createDefaultSkin(){
返回新BasicControlSkin(此);
}
}
私有静态类BasicControlSkin扩展了SkinBase{
受保护BasicControl皮肤(BasicControl控制){
超级(控制);
VBox box=新的VBox();
Label Label=新标签(“此文本应换行,因为它太长”);
label.setWrapText(true);
box.getChildren().add(标签);
getChildren().add(框);
}
}
}
但标签未换行(显示省略号),因为未正确计算控件的首选宽度:

我想得到的是:

如何配置蒙皮以计算蒙皮的首选高度以获得所需的行为(我从不希望显示省略号)

注:

  • 我不想在标签或其他蒙皮组件上设置明确的最大尺寸:
    label.setMaxWidth(150)
    。唯一的显式宽度设置应该是
    开始方法
    中的根
    边框窗格
    。这个宽度(150)可以是可变的,控件可以在不同的地方使用
  • 这个基本控件当然是对真实控件的简化。真正的一个显示多个
    标签
    ,其中包含可变文本
  • 如果我增加窗口高度直到有足够的空间,标签将正确包裹
  • 此代码在OSX 10.10.2上的java 1.8.0_40-b27上运行

AFAIK,要将
文本
包装在
标签
中,您应该为此标签定义
宽度
,因为参考文档:

公共最终无效setWrapText(布尔值)

设置属性wrapText的值

属性描述: 如果一段文本超过标记的的宽度,则此变量指示文本是否应换行

这里的语句超过了标签的宽度说明您已经为
标签定义了
宽度
,这就是为什么在没有定义
宽度
时不能使用它

因此,您的代码应该是:

    Label label = new Label("This text should wrap because it is too long");
    label.setMaxWidth(150);
    label.setWrapText(true);
另一种选择是使用标签而不是
标签
,并使用方法
setWrappingWidth()
,如下所示:

Text t = new Text("This text should wrap because it is too long"  );
t.setWrappingWidth(150);
你会得到这个结果:

结论:

要包装文本(在
标签
文本
元素中),必须定义一个宽度,以便文本在超过此宽度时返回到新行

编辑: 为了使其更具动态性并避免为标签设置宽度,如果要为
borderPane
设置
PrefWidth
,则可以使用
静态双宽度
来获取此
PrefWidth
并将其设置为标签的
MaxWidth
,下面是示例代码:

public class LabelWrap extends Application {

    static double WIDTH;

    public static void main(String[] args) {
        launch(LabelWrap.class);
    }

    @Override
    public void start(Stage stage) throws Exception {
        BasicControl basicControl = new BasicControl();
        BorderPane borderPane = new BorderPane();
        borderPane.setPrefWidth(150);
        borderPane.setCenter(basicControl);

        //get the PrefWidth value in the WIDTH attribute
        WIDTH = borderPane.getPrefWidth();
        stage.setScene(new Scene(borderPane));
        stage.centerOnScreen();
        stage.show();
    }

    private static class BasicControl extends Control {
        @Override
        protected Skin<?> createDefaultSkin() {
                return new BasicControlSkin(this);
        }
    }

    private static class BasicControlSkin extends SkinBase<BasicControl> {
        protected BasicControlSkin(BasicControl control) {
            super(control);
            VBox box = new VBox();
            Label label = new Label("This text should wrap because it is too long");

            //set the WIDTH value to the label MaxWidth
            label.setMaxWidth(WIDTH);
            label.setWrapText(true);
            box.getChildren().add(label);
            this.getChildren().add(box);
        }
    }
}
public类LabelWrap扩展了应用程序{
静态双宽度;
公共静态void main(字符串[]args){
发布(LabelWrap.class);
}
@凌驾
public void start(Stage)引发异常{
BasicControl BasicControl=新的BasicControl();
BorderPane BorderPane=新的BorderPane();
borderPane.setPrefWidth(150);
边框窗格。设置中心(基本控件);
//获取宽度属性中的PrefWidth值
宽度=边框窗格。getPrefWidth();
舞台场景(新场景(边框));
stage.centerOnScreen();
stage.show();
}
私有静态类BasicControl扩展了控件{
@凌驾
受保护的皮肤createDefaultSkin(){
返回新BasicControlSkin(此);
}
}
私有静态类BasicControlSkin扩展了SkinBase{
受保护BasicControl皮肤(BasicControl控制){
超级(控制);
VBox box=新的VBox();
Label Label=新标签(“此文本应换行,因为它太长”);
//将宽度值设置为标签MaxWidth
label.setMaxWidth(宽度);
label.setWrapText(true);
box.getChildren().add(标签);
this.getChildren().add(框);
}
}
}

在8u40 Ubuntu上,它正在被包装。使用borderPane进行尝试。setPrefHeight(50)@UlukBiy我不想只设置边框窗格的高度和宽度。这是对我的用例的简化。我的意思是,当borderPane.setPrefHeight(50)以及窗口的宽度增加或减少时,文本换行按预期工作。显示省略号的原因是,即使包装的文本也没有足够的空间进行渲染。@gontard您是否尝试过将标签的
prefWidth
绑定到VBox的
width属性
wrapText
仅在文本超过标签宽度时才起作用,因此需要为标签定义宽度。尝试添加
label.prefWidthProperty().bind(box.widthProperty())在BasicControlSkin()中。@ItachUchia:在Win7上,这会导致一个非常高(几乎屏幕大小)的窗口。我认为他必须重写computePrefHeight方法