简体   繁体   English

JavaFX setHgrow / 绑定属性无限扩展

[英]JavaFX setHgrow / binding property expanding infinitely

This is my code:这是我的代码:

public class TestPanel extends ScrollPane {

    final int SPACING = 5;
    final int ROW_MAX = 6;

    public TestPanel(ArrayList<Item> items) {

        VBox root = new VBox(); 
        root.setSpacing(SPACING);
        HBox row = null;

        int count = 0;
        for (Item item: items){
            if (count == ROW_MAX || row == null){
                row = new HBox();
                row.setSpacing(SPACING);

                root.getChildren().add(row);
                count = 0;
            }

            CustomBox box = new customBox(item);
            row.getChildren().add(box);

            HBox.setHgrow(box, Priority.ALWAYS);

            //box.prefWidthProperty().bind(row.widthProperty());      // Worked for GridPane

            count++;
        }

        setFitToWidth(true);
        setContent(root);

    }

And this is the custom box node element thing that I'm placing in the V and H Boxes这是我放置在 V 和 H 框中的自定义框节点元素

public class CustomBox extends StackPane {

    private Items item;
    private Rectangle square;

    private int size = 20; // Irrelevent

    public CustomBox(NewAirbnbListing item) {
        this.item= item;

        setPadding(new Insets(5, 5, 5, 5));

        square = new Rectangle(size, size, Color.RED);


        square.widthProperty().bind(widthProperty());
        //square.heightProperty().bind(heightProperty());


        minHeightProperty().bind(widthProperty()); // Maintains aspect ratio

        getChildren().add(square);

    }

The Error: Pink is box, grey is background colour of the StackPane for visual testing.错误:粉红色是方框,灰色是用于视觉测试的 StackPane 的背景颜色。

在此处输入图像描述

What I want to do:我想做的事:

在此处输入图像描述

What I want: I want the rectangle inside the CustomBox (as well as other components I'll add later) to fill up the size of the StackPane which they sit in and alter their size when the window is resized.我想要什么:我希望 CustomBox 内的矩形(以及我稍后将添加的其他组件)填充它们所在的 StackPane 的大小,并在调整 window 大小时改变它们的大小。 I basically want them to mimic the size of that Pane.我基本上希望他们模仿那个窗格的大小。

Now to try explain whats going on, basically I have a class that's basically a square (There's going to be more stuff later) and I want to fill my "grid" with.现在尝试解释发生了什么,基本上我有一个 class,它基本上是一个正方形(稍后会有更多的东西),我想用它填充我的“网格”。 When I first did this I used a GridPane to extend my class, I also used the commented out code to bind the properties and it worked "perfectly", it resized how I wanted with no issues, except the fact it lagged like crazy because the items ArrayList contains thousands of items so this will be a very long list.当我第一次这样做时,我使用 GridPane 来扩展我的 class,我还使用注释掉的代码来绑定属性并且它“完美地”工作,它调整了我想要的大小没有任何问题,除了它像疯了一样滞后的事实因为items ArrayList 包含数千个项目,因此这将是一个很长的列表。 And then later when I was implementing the boxes to store images, that's when the massive lag problems started.后来,当我实现存储图像的盒子时,大量的滞后问题就开始了。 My solution to this was to replace the GridPane with the HBox and VBox combo, and it very much fixed the lag issue, it also lets me do things I can't do with the GridPane.我的解决方案是用 HBox 和 VBox 组合替换 GridPane,它很好地解决了延迟问题,它还让我可以做一些我不能用 GridPane 做的事情。 However, the problem in the gif I linked is what I'm facing.但是,我链接的 gif 中的问题是我面临的问题。 I've tried every combination of binding properties that I can think of but it still expands like crazy and I just have no idea whats causing it so I really hope someone here can help me out.我已经尝试了我能想到的所有绑定属性组合,但它仍然像疯了一样扩展,我只是不知道是什么原因造成的,所以我真的希望这里有人能帮助我。 I don't know tonnes about JavaFX but I'm here to learn, any help is greatly appreciated.我不知道 JavaFX,但我是来学习的,非常感谢任何帮助。

I believe the root cause for your problem lies at: the square width binding with CustomBox width.我相信您的问题的根本原因在于: square宽度与CustomBox宽度绑定。 You might wonder how this is a problem.你可能想知道这是怎么回事。 You are allowing the CustomBox width to be relied on its content (aka square) and your square width is relied on its parent width.. as now these two widths are interdependent to each other.. the width is increased exponentially..您允许 CustomBox 宽度依赖于它的内容(又名正方形),而您的正方形宽度依赖于它的父宽度。因为现在这两个宽度是相互依赖的。宽度呈指数增长。

One possible way to fix this, is to calculate the CustomBox size manually based on the ScrollPane viewport width.解决此问题的一种可能方法是根据 ScrollPane 视口宽度手动计算 CustomBox 大小。 This way you are controlling the parent width manully and the contents width is handled by binding.通过这种方式,您可以手动控制父宽度,而内容宽度由绑定处理。

The code in the TestPanel will be: TestPanel 中的代码将是:

private DoubleProperty size = new SimpleDoubleProperty();

double padding = 4; // 2px on either side
viewportBoundsProperty().addListener((obs, old, bounds) -> {
    size.setValue((bounds.getWidth() - padding - ((ROW_MAX - 1) * SPACING)) / ROW_MAX);
});

CustomBox box = new CustomBox(item);
box.minWidthProperty().bind(size);

A complete working demo is below:一个完整的工作演示如下:

在此处输入图像描述

import javafx.application.Application;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.ScrollPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.IntStream;

public class ScrollPaneContentDemo extends Application {
    @Override
    public void start(Stage stage) throws Exception {
        List<Item> items = new ArrayList<>();
        IntStream.range(1, 1000).forEach(i -> items.add(new Item()));
        TestPanel root = new TestPanel(items);
        Scene scene = new Scene(root, 500, 500);
        stage.setScene(scene);
        stage.setTitle("ScrollPaneContent Demo");
        stage.show();
    }

    class TestPanel extends ScrollPane {
        private final int SPACING = 5;
        private final int ROW_MAX = 6;
        private DoubleProperty size = new SimpleDoubleProperty();

        public TestPanel(List<Item> items) {
            final VBox root = new VBox();
            root.setSpacing(SPACING);
            HBox row = null;
            int count = 0;
            for (Item item : items) {
                if (count == ROW_MAX || row == null) {
                    row = new HBox();
                    row.setSpacing(SPACING);
                    root.getChildren().add(row);
                    count = 0;
                }

                CustomBox box = new CustomBox(item);
                box.minWidthProperty().bind(size);
                row.getChildren().add(box);
                HBox.setHgrow(box, Priority.ALWAYS);
                count++;
            }
            setFitToWidth(true);
            setContent(root);

            double padding = 4;
            viewportBoundsProperty().addListener((obs, old, bounds) -> {
                size.setValue((bounds.getWidth() - padding - ((ROW_MAX - 1) * SPACING)) / ROW_MAX);
            });
        }
    }

    class CustomBox extends StackPane {
        private Item item;
        private Rectangle square;
        private int size = 20;

        public CustomBox(Item item) {
            setStyle("-fx-background-color:#99999950;");
            this.item = item;
            setPadding(new Insets(5, 5, 5, 5));
            square = new Rectangle(size, size, Color.RED);
            square.widthProperty().bind(widthProperty());
            square.heightProperty().bind(heightProperty());

            maxHeightProperty().bind(minWidthProperty());
            maxWidthProperty().bind(minWidthProperty());
            minHeightProperty().bind(minWidthProperty());
            getChildren().add(square);
        }
    }

    class Item {
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM