如何使ListView宽度适合其单元格的宽度 [英] How to make ListView width fit width of its cells

查看:268
本文介绍了如何使ListView宽度适合其单元格的宽度的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个带有自定义单元格工厂的ListView.我计算整个单元格minWidth的最大值,并将其设置为整个ListView的minWidth.因此,受布局中其他区域约束的ListView精确缩小为minWidth.但是将其容纳的单元格调整为首选宽度,而不是最小.结果,节点不适合包含视口,并且显示了水平滚动条.

I have a ListView with custom cell factory. I compute maximum over cells minWidth and set it as minWidth for entire ListView. So the ListView constrained by other regions in the layout is shrunk exactly to minWidth. But cells it holds are resized to preferred width, not minimal. As a result nodes do not fit to containing viewport and horizontal scrollbar is shown.

这太讨厌了.我想使每个单元格完全适合ListView,并摆脱滚动条.更确切.当ListView减小到其最小宽度时,其所有单元格也应减小到该最小宽度.

It's nasty. I'd like to make each cell exactly fit to ListView, and get rid of scrollbar. More precise. When ListView is reduced to its minimal width, all its cells should also be reduced to this minimal width.

我正在寻找一些控制属性,以在没有预定义的开关的情况下切换某些黑客的单元大小调整策略,以实现所描述的行为.

I'm searching for some controlling property that switches cell resizing policy of for some hack to achieve described behavior in case there are no predefined switches.

更新:添加了图形示例

我创建了SplitPane来简化测试布局.我可以通过使用鼠标移动其分隔符来定义布局限制.

I created SplitPane to simplify testing layouts. I can define layout restrictions by moving its separator with mouse.

第一个镜头显示了最初的问题:不考虑单元节点的实际尺寸(最小,最大,优选).即使ListView大于视口宽度,它也始终使用prefWidth.因此,在可以避免的情况下使用水平滚动.

First shot shows the initial problem: actual dimensions (min, max, pref) of cell nodes are not respected. The ListView always use prefWidth even if its greater than viewport width. So horizontal scroll is used when it may be avoided.

之后,我尝试手动设置较小的首选宽度.因此,单元格现在完全可见.这不是解决方案.我给出了这张照片,以证明该单元格的minWidth足够小,可以放入ListView中.

After that I tried to manually set preferred width smaller. So cell now is completely visible. This is not the solution. I give this shot to prove that the cell have sufficiently small minWidth to fit inside the ListView.

最后一枪也很丑.它留下了可能充满单元格内容的可用空间.这是很自然的:如果视口大于首选宽度且小于最大宽度,则应使用该视口来调整单元格内容的大小.

The last shot is ugly too. It leaves free space that may be filled with cell content. It's is natural: if viewport is larger than preferred width and smaller than maximum width, than it should be used for resizing the cell content.

可以通过切换为显式指定的元素的静态大小来解决此问题.但这意味着放弃动态布局的所有好处:程序员每次使用CSS蒙皮时都必须更改大小常量,并且禁止用户调整窗口大小或使用鼠标移动分隔符.

The issue may be suppressed by switching to static sizes of elements specified explicitly. But doing so means to discard all benefits of dynamic layouts: programmer would be obliged to change size constants each time new skin is applied with CSS and user would be prohibited to resize window or move separator with mouse.

这也是一个不好的解决方案.我需要-使javafx的布局引擎正常工作. ListView的最小宽度应该是其单元格的最大最小宽度. ListView的最大宽度应该是其单元格的最小最大宽度. ListView的首选宽度应该是其单元格的最大首选宽度.而且,ListView的实际宽度应该由其父级(在此示例中为SplitPane)针对所有三个布局范围设置.然后将这个大小传递给单元格.

And this is bad solution too. What I need - to make layout engine of javafx work. Minimal width of the ListView should be biggest minimal width of its cells. Maximum width of the ListView should be lowest maximum width of its cells. Preferred width of the ListView should biggest preferred width of its cells. And than actual width of ListView should be set by its parent (SplitPane in this example) with respects to all three layout bounds. And after that this size should be passed to cells.

只有在某些像元最小宽度太大而无法容纳在视口中的情况下,才应显示水平滚动条.

Horizontal scrollbar should be displayed only in case some cell minimal width is too large to fit in viewport.

推荐答案

只需将单元格的prefWidthProperty绑定到ListView的widthProperty.我减去一些边界等等.

Just bind the cell's prefWidthProperty to the ListView's widthProperty. I subtract a bit for borders and such.

使用字符串,您将得到省略号...而不是滚动条.

With strings, you'll get the ellipsis ... instead of a scroll bar.

import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.control.SplitPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.Callback;

public class CellSize extends Application {

    @Override
    public void start(Stage stage) {
        ObservableList<String> items = FXCollections.observableArrayList(
                "hello world", "This is a test", "this is not a drill","vroom...this IS a drill");

        ListView<String> lv = new ListView(items);
        final VBox leftBox  = new VBox(lv,new Button("Unused"));

        lv.setCellFactory(new Callback<ListView<String>, ListCell<String>>() {

            @Override
            public ListCell<String> call(ListView<String> param) {
                ListCell lc = new ListCell<String>() {

                    @Override
                    protected void updateItem(String item, boolean empty) {
                        super.updateItem(item, empty);
                        if (empty) {
                            setText(null);
                            setGraphic(null);
                        } else {
                            setGraphic(null);
                            if (item == null) setText("null");
                            else {
                                setText(item);
                                double minWidth = 5 * item.length();
                                double maxWidth = 10 * item.length();
                                leftBox.setMinWidth(Math.max(minWidth, leftBox.getMinWidth()));
                                leftBox.setMaxWidth(maxWidth);
                            }
                        }
                    }
                };
                lc.prefWidthProperty().bind(lv.widthProperty().subtract(4));
                return lc;
            }
        });

        SplitPane root = new SplitPane();
        root.getItems().addAll(leftBox,new VBox(new Label("Hello")));
        Scene scene = new Scene(root, 300, 250);

        stage.setScene(scene);
        stage.show();

    }

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

}

这篇关于如何使ListView宽度适合其单元格的宽度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆