答案 0 :(得分:0)
我建议扩展Region
以使元素保持在一起并布置子元素。
这更易于实现。我建议使用Path
而不是单独的行,因为这样可以简化尺寸设置。
public class ScaleView extends Region {
private final Label text;
private final Path path;
private final VLineTo down;
private final HLineTo right;
private final VLineTo up;
public ScaleView(String text) {
this();
setText(text);
}
public ScaleView() {
setMaxHeight(USE_PREF_SIZE); // don't resize beyond text size by default
setMinHeight(USE_PREF_SIZE);
text = new Label();
// assemble path for line
down = new VLineTo();
up = new VLineTo();
right = new HLineTo();
down.setAbsolute(false);
up.setAbsolute(false);
right.setAbsolute(false);
path = new Path(new MoveTo(), down, right, up);
path.setStrokeWidth(2);
path.setManaged(false);
getChildren().addAll(text, path);
}
public final StringProperty textProperty() {
return text.textProperty();
}
public final void setText(String value) {
text.setText(value);
}
public final String getText() {
return text.getText();
}
@Override
protected void layoutChildren() {
Insets insets = getInsets();
double left = insets.getLeft();
double top = insets.getTop();
double h = getHeight() - top - insets.getBottom();
double w = getWidth() - left - insets.getRight();
// fix path
down.setY(h);
up.setY(-h);
right.setX(w);
path.relocate(left, top);
layoutInArea(text,
left, top,
w, h,
0,
HPos.CENTER, VPos.CENTER);
}
}
这有点复杂,因为箭头线居中并且使用了不同的笔触。在这种情况下,我将Polygon
用作箭头,将Line
用作两侧的垂直线和箭头线。
public class QuoteView extends Region {
private final Line leftBound;
private final Line rightBound;
private final Line line;
private final Label text;
private final Polygon arrowLeft;
private final Polygon arrowRight;
private final Node[] hOrder;
public QuoteView(String text) {
this();
setText(text);
}
public QuoteView() {
text = new Label();
line = new Line();
// vertical lines
leftBound = new Line();
rightBound = new Line();
leftBound.getStrokeDashArray().setAll(5d);
rightBound.getStrokeDashArray().setAll(5d);
// arrow heads
final double arrowHeight = 15;
final double arrowWidth = 10;
arrowLeft = new Polygon(0, arrowHeight / 2, arrowWidth, 0, arrowWidth, arrowHeight);
arrowRight = new Polygon(0, 0, arrowWidth, arrowHeight / 2, 0, arrowHeight);
arrowLeft.setFill(null);
arrowLeft.setStroke(Color.BLACK);
arrowRight.setFill(null);
arrowRight.setStroke(Color.BLACK);
// nodes that contribute to horizontal size
hOrder = new Node[]{ leftBound, arrowLeft, text, arrowRight, rightBound};
getChildren().addAll(leftBound, arrowLeft, line, arrowRight, rightBound, text);
}
@Override
protected double computePrefHeight(double width) {
Insets insets = getInsets();
double arrowHeight = arrowLeft.getLayoutBounds().getHeight();
double textHeight = text.prefHeight(width);
// preferred height is the height of the arrows
// or 2*textHeight + arrow line height (higher value)
return Math.max(arrowHeight,
2 * textHeight + line.getLayoutBounds().getHeight()) + insets.getBottom() + insets.getTop();
}
@Override
protected double computePrefWidth(double height) {
Insets insets = getInsets();
// the width is computed by putting the vertical lines, arrows and text next to each other
double w = 0;
for (Node n : hOrder) {
w += n.prefWidth(height);
}
return w + insets.getLeft() + insets.getRight();
}
@Override
protected double computeMinHeight(double width) {
Insets insets = getInsets();
double arrowHeight = arrowLeft.getLayoutBounds().getHeight();
double textHeight = text.minHeight(width);
// min height is the height of the arrows
// or 2*textHeight + arrow line height (higher value)
return Math.max(arrowHeight,
2 * textHeight + line.getLayoutBounds().getHeight()) + insets.getBottom() + insets.getTop();
}
@Override
protected double computeMinWidth(double height) {
Insets insets = getInsets();
// the width is computed by putting the vertical lines, arrows and text next to each other
double w = 0;
for (Node n : hOrder) {
w += n.minWidth(height);
}
return w + insets.getLeft() + insets.getRight();
}
public final StringProperty textProperty() {
return text.textProperty();
}
public final void setText(String value) {
text.setText(value);
}
public final String getText() {
return text.getText();
}
@Override
protected void layoutChildren() {
Insets insets = getInsets();
double left = insets.getLeft();
double top = insets.getTop();
double h = getHeight();
double w = getWidth();
// set vertical line size
double contentHeight = h - top - insets.getBottom();
leftBound.setEndY(contentHeight);
rightBound.setEndY(contentHeight);
// layout left arrow & move left vertical line
double x = left;
leftBound.relocate(x, top);
x += leftBound.getLayoutBounds().getWidth();
Bounds bounds = arrowLeft.getLayoutBounds();
arrowLeft.relocate(x, top + (contentHeight - bounds.getHeight()) / 2);
x += bounds.getWidth();
// layout right arrow & move right vertical line
double xEnd = w - insets.getRight() - rightBound.getLayoutBounds().getWidth();
rightBound.relocate(xEnd, top);
bounds = arrowRight.getLayoutBounds();
xEnd -= bounds.getWidth();
arrowRight.relocate(xEnd, top + (contentHeight - bounds.getHeight()) / 2);
// layout line
double lineY = top + (contentHeight - line.getLayoutBounds().getHeight()) / 2;
line.setStartX(x);
line.setStartY(lineY);
line.setEndX(xEnd);
line.setEndY(lineY);
// position text on top of the line
layoutInArea(text,
x, top,
xEnd - x, lineY,
0,
HPos.CENTER, VPos.BOTTOM);
}
}