【问题标题】:How to have images overlap each other in a VBox如何让图像在 VBox 中相互重叠
【发布时间】:2018-02-23 22:58:21
【问题描述】:

我正在使用 Scene Builder 来创建我的场景,我已将卡片 (ImageViews) 添加到 VBoxes 中,所有 12 张卡片似乎都不太适合,尽管它们确实适合我拥有的 HBoxes。我找不到任何可以减少 VBox 内节点间距的属性。我已经展示了我的 VBox 的外观图片,还有一张我的 HBox 的图片(这就是我想要的外观)。如果这不可能,那么我希望能够重叠图像以使其适合。

【问题讨论】:

  • 您的 VBox 的间距属性设置为非零值,或者您的图像顶部有一个小透明区域。你能查一下吗?
  • 实际上最初图像是直接添加的,就像它们在 HBox 中一样,所以我旋转了图像,使它们面向中心,这导致了额外的空间。无论哪种方式,我都无法像 HBox 那样展示 12 张图片。
  • 您可以使用viewportProperty 从您的 ImageView 中定义要使用的特定区域。

标签: javafx-8 scenebuilder


【解决方案1】:

VBox 不支持此功能(至少我不知道会这样)。

但是,如果内容不适合,您可以覆盖 layoutChildren 以向上移动节点,并覆盖 computeMinHeight 以返回 minHeight 值的最大值:

public class OverlappingVBox extends VBox {

    @Override
    protected void layoutChildren() {
        super.layoutChildren();

        List<Node> managed = getManagedChildren();

        int count = managed.size();
        if (count == 0) {
            return;
        }

        double contentAreaMaxY = getHeight() - getInsets().getBottom();

        Node lastNode = managed.get(managed.size() - 1);
        double maxY = lastNode.getLayoutY() + lastNode.getLayoutBounds().getMaxY();

        if (contentAreaMaxY < maxY) {
            // reduce layoutY if content does not fit
            double gap = (contentAreaMaxY - maxY) / (count - 1);
            for (int i = 1; i < count; i++) {
                Node n = managed.get(i);
                n.setLayoutY(n.getLayoutY() + i * gap);
            }
        }

    }

    @Override
    protected double computeMinHeight(double width) {
        // min height = max min height
        double result = 0;
        Insets insets = getInsets();
        double contentWidth = width - insets.getLeft() - insets.getRight();
        for (Node n : getManagedChildren()) {
            double mH = n.minHeight(contentWidth);
            if (mH > result) {
                result = mH;
            }
        }
        return result + insets.getTop() + insets.getBottom();
    }

}

使用示例

@Override
public void start(Stage primaryStage) {
    OverlappingVBox root = new OverlappingVBox();

    Color c = Color.WHITE;

    for (int i = 0; i < 10; i++) {
        root.getChildren().add(new Rectangle(50, 50, c));
        c = c.invert();
    }

    Scene scene = new Scene(root);

    primaryStage.setScene(scene);
    primaryStage.show();
}

【讨论】:

  • 我将如何使用它,记住我使用场景构建器创建了我的 Vbox,它位于 BoarderPane 内。我可以创建一个 OverlappingVbox 对象并通过转换将其设置为我的 Vbox 吗?
  • 您应该能够使用OverlappingVBox 而不是VBox,方法是将&lt;VBox&gt; 元素替换为&lt;OverlappingVBox&gt; 元素(确保添加了适当的&lt;?import ?&gt; 处理指令)。由于OverlappingVBox 扩展了VBox,因此将OverlappingVBox 分配给VBox 字段可以正常工作。 FXMLLoader 将节点注入字段也没有困难...您也可以将布局添加到场景构建器,请参阅stackoverflow.com/questions/30063792/…
  • 这解决了我的大部分问题,但是第一张卡仍然不可见(半覆盖),而底部仍有空间
  • @ScrappyMontana 哎呀,有一个错字maxY 需要计算maxY 而不是maxX 当然...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-06-14
  • 1970-01-01
  • 2013-07-15
  • 2016-03-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多