我对ListView
有一点问题,我不确定是不是因为我遗漏了一些知识,或者我的方法存在缺陷。不得不承认我还不清楚JavaFX在很多情况下如何处理布局。
上面的屏幕截图显示了我使用完全相同的代码得到两次的结果,除了在第二个上是一个看不见的形状我用于连贯布局使得调试可见
CellFactory
扩展Group
所涉及的各个类,我尝试了其他一些Parent
到目前为止没有取得多大成功。
我没有分享我的StarShape
,StarRow
和其他一些misc课程(如果有要求,我很乐意),我写了一个重现该问题的样本。该类扩展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();
}
其中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);
}
}
};
}
以上内容会在ListView<Boolean>
个项目前面显示带有黑色形状的true
(由于tabShape.setVisible(item);
位)。 false
项看起来像常规Label
对象,好像Group
中的隐形形状不存在(但它是)。
调试这个,结果是具有不可见形状的组被赋予负布局X属性值。因此,Label
控件并未对齐,因为我喜欢它们。当我在setLayoutX
之外拨打setLayoutY
和ListView
时(不可见的形状强制偏移),它不会发生,但它可能不是唯一的地方它会发生。
发生了什么以及如何避免它?或者,正如我猜测我接近这个错误的一样,什么是正确的方法?换句话说,我应该问的问题是什么呢?
答案 0 :(得分:13)
从@dlatikay's comment开始,不是将占位符项设置为不可见,而是可以通过将其不透明度设置为0.0
来使其透明。
从你的问题应用到MCVE,这将通过替换:
来完成tabShape.setVisible(item);
使用:
tabShape.setOpacity(item ? 1.0 : 0.0);
就用户体验而言,您可以更进一步。而不是设置&#34;非活动&#34;星星完全透明,您可以将它们设置为接近透明,就像在此模型中一样(不透明度设置为0.1
):
我看到的好处是:
答案 1 :(得分:4)
我猜测我正在接近这个错误的
不,你不是。与所有布局一样,通常有多种方法可以解决同一问题。您的方法实际上是正确的,并且您非常接近工作解决方案。
只需1行更改即可实现您的目标。也就是说,将Group
更改为HBox
。
HBox
确保元素一个接一个地水平排序。它们还允许隐形元素占用空间。
我还注释了一行:label.setLayoutX(40)
。我这样做是因为HBox
不会尊重此设置,实际上您并不需要它。它将根据需要自动水平移动元素。
@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 HBox cellRoot = new HBox();
cellRoot.getChildren().add(tabShape);
cellRoot.getChildren().add(label);
setGraphic(cellRoot);
}
}
当我进行这些更改时,您的布局将呈现如下:
重要:您的示例和屏幕截图略有不同。您可能希望使用VBox
作为明星示例(V代表&#39;垂直&#39;,H代表&#39;水平&#39;)。