Comment faire pour que JavaFX ListView soit la hauteur de ses éléments?

si je crée un ListView:

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

Je m'attendrais à ce qu'il crée une ListView avec 3 lignes. Mais ce n'est pas le cas. Il crée une ListView d'environ 17 lignes. Y a-t-il un moyen de dire à ListView d'être toujours en hauteur de sorte que les éléments qui s'y trouvent soient toujours affichés, mais pas de lignes vides?

avoir une largeur automatique serait également utile, donc il est toujours aussi large que la plus grande rangée.

un des buts de ceci est qu'alors il pourrait être utilisé dans un ScrollPane. Je sais qu'il a ses propres rouleaux, mais ils n'offrent pas un contrôle suffisant.

21
demandé sur mentics 2013-07-02 19:23:09

9 réponses

malheureusement, il n'y a pas une belle propriété de taille propre D'une liste observable à laquelle nous pouvons nous attacher. Au lieu de cela, c'est faisable en ajoutant un ListChangeListener sur la liste, du moins, c'est comme ça que je l'ai fait dans le passé. Par défaut, la taille de chaque ligne devrait être 24px, et nous avons besoin d'un pixel supplémentaire en haut et en bas pour les bords de la ListView. Sinon, nous avons toujours la barre de défilement de ListView. Tout d'abord, nous allons créer L'ObservableList et la ListView, et définir la hauteur initiale de la ListView:

/*
 * Each row in a ListView should be 24px tall.  Also, we have to add an extra
 * two px to account for the borders of the ListView.
 */
final int ROW_HEIGHT = 24;
final ObservableList items = FXCollections.observableArrayList("1", "2", "3");
final ListView list = new ListView(items);

// This sets the initial height of the ListView:
list.setPrefHeight(items().size() * ROW_HEIGHT + 2);

maintenant nous devons ajouter un ListChangeListener à la liste observable. Lorsque la liste Change, nous changeons simplement la hauteur définie de ListView pour correspondre au nouveau nombre de lignes. Si nous savons que nous n'allons jamais ajouter ou supprimer des éléments de la liste Observablequi soutient ListView, alors nous pouvons exclure l'auditeur. Encore une fois, la hauteur est le nombre de lignes multiplié par la hauteur par ligne plus deux pixels supplémentaires pour le frontières:

/*
 * This listener will resize the ListView when items are added or removed
 * from the ObservableList that is backing the ListView:
 */
items.addListener(new ListChangeListener() {
    @Override
    public void onChanger(ListChangeListener.Change change) {
        list.setPrefHeight(items.size() * ROW_HEIGHT + 2);
    }
});

Références: JavaFX ListView Documentation,JavaFX ObservableList Documentation

7
répondu Paul Marshall 2013-07-03 19:26:45

je viens de découvrir que la réponse de Paul Marshall peut être réduite à une simple doublure fixations.taille qui crée une propriété JFX numérique représentant la taille D'une liste observable:

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

la hauteur des cellules list doit malheureusement toujours être codée en AFAIK.

5
répondu Alexandre Mazari 2014-01-28 14:33:00

vous Êtes à la recherche pour que:

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

masquer le vide de la cellule.

3
répondu tonimaroni 2013-12-29 22:50:46

j'ai trouvé une solution relativement facile mais encore légèrement hacky qui fonctionne sous l'hypothèse que toutes les cellules non vides ont la même hauteur: au lieu d'analyser css ou quelque chose comme ça, ajouter un InvalidationListener pour votre listView.getItems(); la première fois vos éléments de liste est non-vide, vous récursive passer par l' ListCell où !cell.isEmpty(), et de stocker la valeur de cell.getHeight(). Assurez-vous d'envelopper ce code dans une balise Platform.runLater() pour qu'il soit exécuté une fois le ListView layouting est fait. Une fois que vous avez cette taille, vous la multipliez par listView.getItems().size() et appeler listView.setMaxHeight avec la valeur résultante (toujours à l'intérieur de l' InvalidationListener).

3
répondu warakawa 2015-05-20 07:01:40

le système de réputation de StackOverflow m'empêche de commenter la réponse de Paul Marshall, mais je voulais ajouter pour quiconque regardant ceci que son estimation de 24px pour rows est" généralement "confirmée par la documentation officielle de JavaFX-voir "fixedCellSize" à http://download.java.net/jdk8/jfxdocs/javafx/scene/control/ListView.html:

généralement les cellules sont autour de 24px...

ainsi, Alors que je suis d'accord que "[f]iguring hors ligne hauteur, largeur de bordure, etc., d'une certaine façon, le style ou les trucs délicats sont compliqués, mais probablement la seule façon de le faire" peut être vrai, en commençant par une hypothèse qui est soutenue par la documentation officielle est un bon endroit pour commencer, et semble donner lieu à des listes d'apparence décente dans mes tests sur une ListView (en utilisant Java 7).

1
répondu Nate Simpson 2013-10-15 08:18:21

Essayez de setPrefHeight(double) dans la sous-classe de ListCell. Par exemple dans mon code

@Override
public void updateItem(File item, boolean empty)
{
  super.updateItem(item, empty);
  if (empty) {
    setText(null);
    setGraphic(null);
  } else {
    setText(item.getName());
    setGraphic(null);
    setPrefHeight(getSize(item)/getsize(folder));
  }
}
0
répondu Alexmelyon 2014-12-04 09:51:15

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>
}
0
répondu Rogerio Souza 2016-08-07 00:08:54

j'ai basé ma réponse sur les réponses fournies par @scribbleslims et @Alexandre Mazari

listView.setPrefHeight(listView.getItems().size() * LIST_CELL_HEIGHT);

Vous devez définir LIST_CELL_HEIGHT sur votre propre.

Dans mon cas, j'ai utilisé 29.501.

0
répondu Coder Typist 2018-05-17 23:40:20

exemple D'Image pour définir la hauteur de ListView

si vous avez une liste statique, vous pouvez définir la hauteur de vue de liste avec la méthode setter qui vient avec la classe ListView setPrefHeight

ListView.setPrefHeight(140);
-1
répondu scribbleslims 2018-04-09 11:36:35