29

ListView を作成する場合:

new ListView<>(FXCollections.observableArrayList("1", "2", "3"))

3行のListViewを作成することを期待しています。しかし、そうではありません。17 行ほどの ListView を作成します。ListView に常に高さを指定して、その中にあるアイテムは常に表示されますが、空白行は表示されないようにする方法はありますか?

自動幅も便利なので、常に最も広い行と同じ幅になります。

これの目的の 1 つは、ScrollPane で使用できるようにすることです。独自のスクロールバーがあることは知っていますが、十分な制御ができません。

4

10 に答える 10

11

ObservableList のサイズを表す数値 jfx プロパティを作成するBindings.sizeを使用して、Paul Marshall の回答をワンライナーに要約できることがわかりました。

listView.prefHeightProperty().bind(Bindings.size(itemListProperty).multiply(LIST_CELL_HEIGHT));

残念ながら、リストのセルの高さはまだハードコーディングされている必要があります。

于 2014-01-28T14:33:00.327 に答える
5

あなたはそれを探していますか:

.list-cell:empty {
    -fx-opacity: 0;
}

これにより、空のセルが非表示になります。

于 2013-12-29T22:50:46.340 に答える
3

空ではないすべてのセルが同じ高さであるという仮定の下で機能する、比較的簡単ですが、まだ少しハックなソリューションを見つけました。cssなどを解析する代わりにInvalidationListenerlistView.getItems(); items リストが初めて空でなくなると、 whereListViewのインスタンスが見つかるまで s の子を再帰的に調べ、の値を保存します。レイアウトが完了したら実行されるように、必ずそのコードを でラップしてください。その高さを取得したら、それを掛けて、結果の値で呼び出します (まだ の中にあります)。ListCell!cell.isEmpty()cell.getHeight()Platform.runLater()ListViewlistView.getItems().size()listView.setMaxHeightInvalidationListener

于 2015-05-20T07:01:40.790 に答える
2

@warakawaの回答に基づいて一生懸命働いた後、解決策を見つけました。ご存知のように、Listview の実装は多くの頭痛の種を引き起こしています。このため、「PREF_SIZE」の問題を修正する 2 つのクラスを作成しました (高さの定数は 400 で、幅は高さに応じて計算されます)。私が作成したスキンクラスは、期待どおりにサイズを計算し、新しいプロパティ「fillWidth」が「true」に変更されたときに醜い水平バーを防ぎます。このプロパティにより、セルが可能な限り水平に成長します。よろしく。

ListViewFixed.java

package javafxapplication;

import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.scene.control.Skin;

public class ListViewFixed<T> extends javafx.scene.control.ListView<T>
{
    // <editor-fold defaultstate="collapsed" desc="Properties">
    private final BooleanProperty fillWidth = new SimpleBooleanProperty(this, "fillWidth");

    public final BooleanProperty fillWidthProperty()
    {
        return fillWidth;
    }

    public final boolean isFillWidth()
    {
        return fillWidth.get();
    }

    public final void setFillWidth(boolean fillWidth)
    {
        this.fillWidth.set(fillWidth);
    }
    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="Methods">
    @Override
    protected Skin createDefaultSkin()
    {
        return new ListViewFixedSkin(this);
    }
    // </editor-fold>
}

ListViewFixedSkin.java

package javafxapplication;

import java.util.Set;
import javafx.beans.Observable;
import javafx.geometry.Insets;
import javafx.geometry.Orientation;
import javafx.scene.Node;
import javafx.scene.control.IndexedCell;
import javafx.scene.control.ScrollBar;
import javafx.scene.layout.Region;

public class ListViewFixedSkin extends com.sun.javafx.scene.control.skin.ListViewSkin
{
    // <editor-fold defaultstate="collapsed" desc="Fields">
    private ListViewFixed listView;
    private ScrollBar scrollBarHorizontal;
    private ScrollBar scrollBarVertical;
    private boolean fillWidthCache;
    private double prefWidthCache;
    private Region placeholderRegion;
    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="Constructors">
    public ListViewFixedSkin(ListViewFixed listView)
    {
        super(listView);

        this.listView = listView;

        registerChangeListener(listView.fillWidthProperty(), "FILL_WIDTH");
    }
    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="Methods">
    private void updateFillWidth()
    {
        if (scrollBarHorizontal != null && scrollBarVertical != null && fillWidthCache != listView.isFillWidth())
        {
            if (listView.isFillWidth() && !fillWidthCache)
            {
                scrollBarHorizontal.visibleProperty().addListener(this::updateCellsPrefWidth);
                scrollBarVertical.visibleProperty().addListener(this::updateCellsPrefWidth);
            }
            else
            {
                scrollBarHorizontal.visibleProperty().removeListener(this::updateCellsPrefWidth);
                scrollBarVertical.visibleProperty().removeListener(this::updateCellsPrefWidth);
            }

            fillWidthCache = listView.isFillWidth();
        }
    }

    private void updateCellsPrefWidth(Observable o)
    {
        final Insets insets = getSkinnable().getInsets();
        final double prefWidth = getSkinnable().getWidth() + insets.getLeft() + insets.getRight() - scrollBarVertical.getWidth();

        if (prefWidth != prefWidthCache)
        {
            for (int i = 0; i < flow.getCellCount(); i++)
            {
                final IndexedCell cell = flow.getCell(i);

                if (!cell.isEmpty())
                {
                    cell.setPrefWidth(prefWidth);
                }
            }

            prefWidthCache = prefWidth;
        }
    }

    private boolean showingPlaceHolder()
    {
        checkState();

        if (getItemCount() == 0)
        {
            if (placeholderRegion == null)
            {
                updatePlaceholderRegionVisibility();

                final Object obj = getChildren().get(getChildren().size() - 1);
                if (obj instanceof Node && ((Region) obj).getStyleClass().contains("placeholder"))
                {
                    placeholderRegion = (Region) obj;
                }
            }

            if (placeholderRegion != null)
            {
                return true;
            }
        }

        return false;
    }

    @Override
    protected void handleControlPropertyChanged(String p)
    {
        super.handleControlPropertyChanged(p);
        if ("FILL_WIDTH".equals(p))
        {
            updateFillWidth();
        }
    }

    @Override
    protected double computePrefHeight(double width, double topInset, double rightInset, double bottomInset, double leftInset)
    {
        if (showingPlaceHolder())
        {
            return super.computePrefHeight(width, topInset, rightInset, bottomInset, leftInset);
        }
        else
        {
            double computedHeight = topInset + bottomInset;

            for (int i = 0; i < flow.getCellCount(); i++)
            {
                final IndexedCell cell = flow.getCell(i);

                if (!cell.isEmpty())
                {
                    computedHeight += cell.getHeight();
                }
            }

            return computedHeight;
        }
    }

    @Override
    protected double computePrefWidth(double height, double topInset, double rightInset, double bottomInset, double leftInset)
    {
        double computedWidth = 0;

        if (showingPlaceHolder())
        {
            computedWidth += placeholderRegion.getLayoutBounds().getWidth();
        }
        else
        {
            for (int i = 0; i < flow.getCellCount(); i++)
            {
                final IndexedCell cell = flow.getCell(i);

                if (!cell.isEmpty() && cell.getWidth() > computedWidth)
                {
                    computedWidth = cell.getWidth();
                }
            }

            if (scrollBarVertical != null && scrollBarVertical.isVisible())
            {
                computedWidth += scrollBarVertical.getWidth();
            }
        }

        if (computedWidth != 0)
        {
            return computedWidth + leftInset + rightInset;
        }
        else
        {
            return super.computePrefWidth(height, topInset, rightInset, bottomInset, leftInset);
        }
    }

    @Override
    protected void layoutChildren(double x, double y, double w, double h)
    {
        super.layoutChildren(x, y, w, h);

        if (scrollBarHorizontal == null || scrollBarVertical == null)
        {
            final Set<Node> nodes = getSkinnable().lookupAll(".scroll-bar");

            nodes.stream().forEach((node) ->
            {
                if (node instanceof ScrollBar)
                {
                    final ScrollBar scrollBar = (ScrollBar) node;

                    if (scrollBar.getOrientation() == Orientation.HORIZONTAL)
                    {
                        scrollBarHorizontal = scrollBar;
                    }
                    else
                    {
                        scrollBarVertical = scrollBar;
                    }
                }
            });

            updateFillWidth();
        }
    }

    @Override
    public void dispose()
    {
        if (fillWidthCache)
        {
            scrollBarHorizontal.visibleProperty().removeListener(this::updateCellsPrefWidth);
            scrollBarVertical.visibleProperty().removeListener(this::updateCellsPrefWidth);
        }

        listView = null;

        super.dispose();
    }
    // </editor-fold>
}

警告 ListViewFixedSkin.java クラスで行うべきいくつかの修正があります。メソッドを直接参照渡しする場合は、前に変数に格納してから、追加/添付/削除/分離メソッドで変数を渡します。そうしないと、メモリの問題が発生する可能性があります。

于 2016-08-07T00:02:24.077 に答える
0

ListView の高さを設定するイメージの例

静的リストがある場合は、ListView クラスの setPrefHeight に付属のセッター メソッドでリスト ビューの高さを設定できます。

ListView.setPrefHeight(140);
于 2018-04-09T11:36:35.440 に答える