Javafx:如何将单元格宽度限制为ListView的宽度

时间:2016-05-10 05:44:06

标签: javafx-8

一直在努力解决这个问题。

我希望列表单元格限制为父ListView的宽度,并且如果文本被裁剪/超限,则包含的文本将显示省略号点。

但无论我做什么,所有细胞的宽度都会增长到这些细胞中最长文本的长度。并且超越单元格中的文本被“剪切”而不是我想要的省略号。

我的ListView在fxml中定义:

<BorderPane fx:id="listViewResultsParentPane">
    <center>
        <ListView fx:id="listViewResults"/>
    </center>
</BorderPane>

我有一个列表单元格类:

public class ResultsListCell extends ListCell<ResultsListItem> {
    @Override
    public void updateItem(final ResultsListItem item, final boolean empty) {
        super.updateItem(item, empty);
        if(empty || item == null){
            setText("");
        } else {
            setText(item.title);
            setTextOverrun(OverrunStyle.ELLIPSIS);
            setEllipsisString("...");
        }
    }
}

为了摆脱水平滚动条,我正在使用这个css:

.list-view#listViewResults .scroll-bar:horizontal .increment-arrow,
.list-view#listViewResults .scroll-bar:horizontal .decrement-arrow,
.list-view#listViewResults .scroll-bar:horizontal .increment-button,
.list-view#listViewResults .scroll-bar:horizontal .decrement-button {
    -fx-padding:0;
}

设置/限制我尝试过的细胞的宽度:

  • 将每个单元格的宽度设置为父级的宽度 updateCell调用。
  • 绑定prefHeight和maxHeight属性 每个单元格与父级单元格
  • 将单元格css属性的maxHeight和prefHeight设置为100%

任何帮助都将不胜感激。

2 个答案:

答案 0 :(得分:10)

<强>解决方案

将每个单元格的宽度绑定到列表的首选宽度,少于几个像素以允许列表边框。并将每个单元格的最大宽度设置为其首选大小:

prefWidthProperty().bind(list.widthProperty().subtract(2));
setMaxWidth(Control.USE_PREF_SIZE);

您不需要任何自定义CSS来删除水平滚动条。仅当显示的列表单元格超出ListView的宽度并且上面指定的约束确保永远不会发生时,才会显示水平滚动条。您也不需要为单元格设置文本溢出样式和省略号字符串,因为这些将默认设置为您想要的值。

sample app

完成示例程序

import javafx.application.Application;
import javafx.collections.*;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.stage.Stage;

public class ElidedListView extends Application {
    @Override
    public void start(Stage stage) {
        ListView<String> list = new ListView<>();
        ObservableList<String> items = FXCollections.observableArrayList(
                "Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
                "Aenean nibh ipsum, semper nec ipsum quis, dignissim gravida arcu.",
                "Sed posuere auctor magna vel suscipit.",
                "Aenean eu diam at dolor auctor porta.",
                "Integer tincidunt ex metus, in euismod velit facilisis in.",
                "Praesent purus mi, mattis rutrum egestas vitae, elementum vel dolo"
        );
        list.setItems(items);
        list.setCellFactory(param -> new ListCell<String>() {
            {
                prefWidthProperty().bind(list.widthProperty().subtract(2));
                setMaxWidth(Control.USE_PREF_SIZE);
            }
            @Override
            protected void updateItem(String item, boolean empty) {
                super.updateItem(item, empty);

                if (item != null && !empty) {
                    setText(item);
                } else {
                    setText(null);
                }
            }
        });

        stage.setScene(new Scene(list));
        stage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}

答案 1 :(得分:3)

一种更简单和更好的解决方案是将列表单元格的首选宽度设置为0.无论如何,列表单元格将调整为列表的视口宽度,但它不会比可用空间更宽。这有效地隐藏了水平滚动条,有/无垂直滚动条正确反应,不需要任何绑定。 (唯一的例外是计算出的最小宽度高于列表视图宽度的列表单元格)

list.setCellFactory(l -> new ListCell<String>() {
    { // constructor
        setPrefWidth(0); // avoids the issues
    }

    @Override
    protected void updateItem(String item, boolean empty) {
        super.updateItem(item, empty);
        // do whatever you like
    }
});