我创建了扩展 StackPane 的 TitledBorderedPane 类。我使用 Shape 对象来创建 Rectangle 和 Text。该类包含一个包含内容的容器 StackPane 对象。以下代码是不言自明的。
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.shape.Shape;
import javafx.scene.text.Text;
public class TitledBorderedPane extends StackPane{
private final StackPane container;
private final Group shapeGroup = new Group();
private final Rectangle rect;
private final Rectangle rectRemove;
private final Text title;
public TitledBorderedPane(String titleText) {
container = new StackPane();
//Rectangle to create border
//Initial size of the rectangle is not important
//as it is set with action listener.
rect = new Rectangle(0, 0, 200, 200);
rect.setStroke(Color.BLACK);
rect.setFill(null);
rect.setStrokeWidth(1);
rect.setArcWidth(10.0);
rect.setArcHeight(10.0);
//Border title text
title = new Text(20.0, 4.0, titleText);
//Rectangle to remove part of the border to fit the text
rectRemove = new Rectangle(15, -2, title.getBoundsInLocal().getWidth() + 10, 5);
//Set padding of the container, so the content of the container
//does not overlap the border
container.setPadding(new Insets(title.getBoundsInLocal().getHeight() + 5));
super.getChildren().addAll(shapeGroup, container);
//Add action listeners to width and height properties
widthProperty().addListener(
(observable, oldvalue, newvalue) -> {
rect.setWidth((double)newvalue - title.getBoundsInLocal().getHeight());
setShape();
}
);
heightProperty().addListener(
(observable, oldvalue, newvalue) -> {
rect.setHeight((double)newvalue - title.getBoundsInLocal().getHeight());
setShape();
}
);
//The style should not be used here. I have used it only for the example.
setStyle("-fx-background-color: rgba(0, 100, 100, 0.5); -fx-background-radius: 0;");
}
private void setShape() {
Shape shape = Shape.subtract(rect, rectRemove);
shape.setSmooth(true);
shapeGroup.getChildren().clear();
shapeGroup.getChildren().addAll(shape, title);
}
/**
* Returns ObservableList of the container pane
*
* @return
*/
@Override
public ObservableList<Node> getChildren() {
return container.getChildren();
}
}
该类可以用作普通的 StackPane。它给出了以下结果。
