带有自定义CellFactory的ListView修剪不可见节点

Lul*_*ero 45 java layout listview javafx

我的布局问题

我有一点问题,ListView我不确定是不是因为我遗漏了一些知识,或者我的方法存在缺陷.不得不承认我还不清楚JavaFX在很多可能情况下如何处理布局.

ListView修剪我的布局尝试

上面的屏幕截图显示了我使用完全相同的代码获得两次的结果,除了在第二个屏幕截图中,我用于连贯布局的不可见形状对于调试是可见的.

CellFactory扩展所涉及的各种类Group,Parent到目前为止我尝试了其他一些没有太大成功.


如何重现

而不是共享我的StarShape,StarRow和其他一些杂项类(我很乐意,如果需要)我写了一个样本复制的问题.该类扩展Application并覆盖该start(...)方法:

@Override
public void start(Stage primaryStage) throws Exception {
    final StackPane root = new StackPane();
    final Scene scene = new Scene(root, 400, 600);

    final ListView<Boolean> listView = new ListView<>();
    listView.setCellFactory(this::cellFactory);

    for (int i = 0; i < 5 ; i++) {
        listView.getItems().add(true);
        listView.getItems().add(false);
    }

    root.getChildren().add(listView);

    primaryStage.setScene(scene);
    primaryStage.setTitle("ListView trims the invisible");
    primaryStage.show();
}
Run Code Online (Sandbox Code Playgroud)

这里this::cellFactory

private ListCell<Boolean> cellFactory(ListView<Boolean> listView) {
    return new ListCell<Boolean>() {
        @Override
        protected void updateItem(Boolean item, boolean empty) {
            super.updateItem(item, empty);

            if (empty || item == null) {
                setText(null);
            } else {
                final Rectangle tabShape = new Rectangle();
                tabShape.setHeight(20);
                tabShape.setWidth(40);
                tabShape.setVisible(item);

                final Label label = new Label(item.toString());
                label.setLayoutX(40);

                final Group cellRoot = new Group();
                cellRoot.getChildren().add(tabShape);
                cellRoot.getChildren().add(label);

                setGraphic(cellRoot);
            }
        }
    };
}
Run Code Online (Sandbox Code Playgroud)

以上将ListView<Boolean>true项目前面显示黑色形状(因为tabShape.setVisible(item);位).这些false物品看起来像普通Label物体,好像它们Group中不可见的形状不存在(但它是).


结束评论

调试这个,结果表明具有不可见形状的组被赋予负布局X属性值.因此,Label控件并不像我希望的那样对齐.当我打电话setLayoutX和a setLayoutY之外ListView(不可见的形状强制偏移)时,它不会发生,但它可能不是它发生的唯一地方.

发生了什么以及如何避免它?或者,因为我猜我正在接近这个错误,是正确的方法吗?换句话说,我应该问的问题是什么?

Rob*_*sen 13

@ dlatikay的评论中获取,不是将占位符项设置为不可见,而是通过将其不透明度设置为透明来呈现它们0.0.

从你的问题应用到MCVE,这将通过替换:

tabShape.setVisible(item);
Run Code Online (Sandbox Code Playgroud)

有:

tabShape.setOpacity(item ? 1.0 : 0.0);
Run Code Online (Sandbox Code Playgroud)

在用户体验方面,您可以更进一步.您可以将它们设置为接近透明,而不是将"非活动"星形设置为完全透明,就像在此模型中一样(不透明度设置为0.1):

小样

我看到的好处是:

  1. 它不仅表示列表中项目的评级,还表示最大评级.
  2. 它避免了零星的列表项的尴尬空白空间.