JavaFX 2:包含文本的可调整大小的矩形

时间:2014-07-30 16:50:11

标签: java binding javafx javafx-2

我想显示一个包含文本/标签的矩形。为此,我创建了一个堆栈窗格,并为其添加了一个矩形和一个标签。但是文本/标签未正确居中。它位于矩形之外(左侧)。这是我目前使用的代码:

createRectangle(String name) {
   pane = new StackPane();
   text = new Label(name);
   rect = new Rectangle();
   // bind rectangle width to text width and add 10 
   rect.widthProperty().bind(text.widthProperty().add(10));
   rect.heightProperty().bind(text.heightProperty().add(10));

   // add to stackpane
   pane.getChildren().addAll(rect,text);

   // display stackpane
   getChildren().add(pane)
}

我尝试绑定矩形的xProperty()和yProperty(),更改stackpane(setAlignment(Pos.CENTER))和其他内容的对齐方式,但没有成功。

当我使用固定的矩形大小(例如新的矩形(30,30))并且不使用绑定时,标签在矩形内正确居中。但是,矩形的大小需要根据标签大小进行调整:

// label is placed correctly in the center of the rectangle
createRectangle(String name) {
   pane = new StackPane();
   text = new Label(name);
   rect = new Rectangle(30,30);

   // add to stackpane
   pane.getChildren().addAll(rect,text);

   // display stackpane
   getChildren().add(pane)
}

1 个答案:

答案 0 :(得分:8)

对于标注背景的背景

只需在Label上直接使用CSS,您就不需要任何其他节点。

Label label = new Label("Sally collects seashells on the seashore");
label.setStyle("-fx-background-color: coral; -fx-padding: 10px;");

填充可用于调整标签周围矩形背景区域的大小。

fixed label

适用于可调整大小的背景

您不需要Rectangle节点,将标签放在StackPane中并在StackPane上设置背景:

Label label = new Label("Sally collects seashells on the seashore");
StackPane centeredLabel = new StackPane(label);
centeredLabel.setStyle("-fx-background-color: coral;");

centered label

可执行样本

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

public class LabelBackground extends Application {
    @Override
    public void start(Stage stage) throws Exception {
        Label label = new Label("Sally collects seashells on the seashore");
        StackPane centeredLabel = new StackPane(label);
        centeredLabel.setStyle("-fx-background-color: coral;");

        StackPane root = new StackPane(centeredLabel);
        root.setPadding(new Insets(10));

        stage.setScene(new Scene(root));
        stage.show();
    }

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

注意:本答案中的内联样式仅用于演示目的,最佳做法是使用CSS样式表进行CSS样式定义。

  

我还想使用其他形状(尤其是圆角矩形和圆形)而不是普通的矩形。这可以通过设置堆栈窗格或标签本身来实现吗?

是的,任何派生自Region(包括StackPane等布局窗格和Label等控件)的内容都可以通过CSS进行相当广泛的设计。

要获得圆角背景,您可以使用-fx-background-radius

要获得任意形状的背景,您可以使用fx-shape,但您可能会发现将文本放置在任意形状的背景中很棘手。

你也可以在代码中编写一个形状,并使用绑定来使你的东西适合你最初在你的问题中尝试。

如果事情需要进行大量的微调,那么你可以对region进行子类化并覆盖layoutChildren方法,以便对该方法中的所有子进行精确的布局计算(这就是大多数内置JavaFX的方式)控件处理其皮肤类中的布局。)

无论如何,一个看似简单的问题并不总是有一个简单的答案,因为在你做事的方式和你可能想要做的事情的许多细微差别方面会有很多变化,例如如何处理包装文本,插入内容,是否删除超出最小大小的文本等。

但是,对于矩形或圆角矩形背景的最常见任务,我只是坚持直接在标签上使用CSS样式。通过使用样式表,您可以轻松地完全更改标签的应用程序样式。

这是一个更广泛的过度杀伤样本:

lotsastyles

LabelBackground.java

import javafx.application.Application;
import javafx.beans.binding.DoubleBinding;
import javafx.geometry.*;
import javafx.scene.*;
import javafx.scene.control.Label;
import javafx.scene.layout.*;
import javafx.scene.shape.Ellipse;
import javafx.stage.Stage;

public class LabelBackground extends Application {
    @Override
    public void start(Stage stage) throws Exception {
        Pane starLabel = labelOnStyledBackground(
                "Practical Principles of Plain and Perfect Pronunciation.",
                "star-label"
        );

        StackPane labelOnResizableBackground = labelOnStyledBackground(
                "Sally collects seashells on the seashore",
                "resizable-background"
        );
        labelOnResizableBackground.setPrefHeight(60);

        Label squareLabel = createLabel(
                "Betty Botter bought a bit of butter.",
                "square-label"
        );

        Label roundedLabel = createLabel(
                "Peter Piper picked a peck of pickled peppers.",
                "rounded-label"
        );

        Node ellipticalLabel = createEllipticalLabel(
                "Round and round the rugged rock the ragged rascal ran.",
                "elliptical-label"
        );

        VBox root = new VBox(
                10,
                starLabel,
                labelOnResizableBackground,
                squareLabel,
                roundedLabel,
                ellipticalLabel
        );
        VBox.setVgrow(labelOnResizableBackground, Priority.SOMETIMES);
        root.setAlignment(Pos.TOP_CENTER);
        root.setPadding(new Insets(10));

        Scene scene = new Scene(root);
        scene.getStylesheets().add(
                LabelBackground.class.getResource(
                        "label-styles.css"
                ).toExternalForm()
        );
        stage.setScene(scene);
        stage.setTitle("Resize me!");
        stage.show();
    }

    private Label createLabel(String text, String styleClass) {
        Label label = new Label(text);
        label.getStyleClass().add(styleClass);

        return label;
    }

    private StackPane labelOnStyledBackground(String text, String styleClass) {
        Label label = new Label(text);
        StackPane container = new StackPane(label);
        container.getStyleClass().add(styleClass);

        return container;
    }

    private Group createEllipticalLabel(String text, String styleClass) {
        final double INSET = 20;

        Label label = new Label(text);

        Ellipse ellipse = new Ellipse();
        ellipse.getStyleClass().add("ellipse");

        DoubleBinding halfWidth  = label.widthProperty().divide(2).add(INSET);
        DoubleBinding halfHeight = label.widthProperty().divide(4).add(INSET);

        ellipse.radiusXProperty().bind(halfWidth);
        ellipse.radiusYProperty().bind(halfHeight);

        ellipse.centerXProperty().bind(halfWidth);
        ellipse.centerYProperty().bind(halfHeight);

        label.setLayoutX(INSET);
        label.layoutYProperty().bind(halfHeight.subtract(label.heightProperty().divide(2)));

        Group group = new Group(ellipse, label);
        group.getStyleClass().add(styleClass);

        return group;
    }

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

标签styles.css的

.root {
    -fx-font-size: 16px;
}

.rounded-label {
    -fx-background-color: cadetblue;
    -fx-padding: 10px;
    -fx-background-radius: 10px;
}

.square-label {
    -fx-background-color: plum;
    -fx-padding: 10px;
}

.star-label {
    -fx-background-color: gold;
    -fx-padding: 120px;
    /* shape courtesy of Smiffy's star place: http://www.smiffysplace.com/stars.html */
    -fx-shape: "M 0.000 20.000 L 23.511 32.361 L 19.021 6.180 L 38.042 -12.361 L 11.756 -16.180 L 0.000 -40.000 L -11.756 -16.180 L -38.042 -12.361 L -19.021 6.180 L -23.511 32.361 L 0.000 20.000";
}

.resizable-background {
    -fx-background-color: coral;
}

.elliptical-label .ellipse {
    -fx-fill: lightpink;
}

如果您对进一步的样品非常热衷,请查看QuoteMaker app处理可调整大小标签背景样式的方式。