2013-07-02 13 views
18

。しかし、それはしません。これは、17またはそれ以上の行のListViewを作成します。 ListViewに常にアイテムの高さを指示する方法はありますか?そのアイテムは常に表示されますが、空白の行はありません。JavaFX ListViewをアイテムの高さにするにはどうすればよいですか?</p> <pre><code>new ListView<>(FXCollections.observableArrayList("1", "2", "3")) </code></pre> <p>が、私はそれが3行でリストビューを作成することを期待する:私は、ListViewコントロールを作成する場合

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

この目的の1つは、ScrollPaneで使用できるということです。私はそれがそれ自身のスクロールバーを持っていることを知っています、しかし、彼らは十分なコントロールを提供していません。

+0

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(HTTP [CSSをリストビューに追加の空白行が表示されないように]:// fxexperience .com/2011/11/alternate-row-highlighting-in-empty-tableview-and-listview-rows /)。 ListView自体のサイズをアイテムの高さに合わせるのと同じではありませんが、おそらくそれで十分です。 – jewelsea

+0

@ jewelsea私はそれの例を見ましたが、それは私が必要とするものではありません。 – mentics

+0

ご要望に合わせて、[ScrollPane](http:// docs(英語))で[VBox](http://docs.oracle.com/javafx/2/api/javafx/scene/layout/VBox.html) .oracle.com/javafx/2/api/javafx/scene/control/ScrollPane.html)を使用してください。 – jewelsea

答えて

6

私たちがバインドするObservableListには、残念ながらnice、clean sizeプロパティはありません。代わりにリストにListChangeListenerを追加することでやりとりできます。これは少なくとも私が過去に行ったことです。デフォルトでは、各行のサイズは24ピクセルでなければならず、ListViewのエッジの上下に余分なピクセルが必要です。それ以外の場合は、ListViewのスクロールバーが表示されます。今、私たちはObservableListにListChangeListenerを追加する必要が

/* 
* 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); 

:まず、ObservableListとリストビューを作成し、リストビューの初期高さを設定します。リストが変更されると、新しい行数に一致するようにListViewの高さを変更するだけです。 ObservableListからListViewをバッキングしている項目を追加または削除しないことがわかっている場合、そのListenerを除外できます。

/* 
* 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); 
    } 
}); 

参考:ここでも、高さは国境の行に加えて2個の余分なピクセルあたりの高さが倍の行数がある JavaFX ListView DocumentationJavaFX ObservableList DocumentationにStackOverflowの評判システムは、ポール・マーシャルの上のコメントから私を妨げている

+0

行の高さを24にハードコードすることは受け入れられず、境界についての仮定も信頼できません。どのようにスタイリングやトリッキーなものから何か行の高さ、境界線の幅などを調べるのは面倒ですが、おそらくそれを行う唯一の方法です。ありがとう! – mentics

+0

なぜ 'list.lookup("。list-cell ")。getHeight()'?これにより、CSSでサイズを設定することができます。 – Mordechai

1

行の彼は24px推定は、「一般」公式JavaFXの文書によって確認されていることの答えが、私はこれを見て、誰のために追加したい - http://download.java.net/jdk8/jfxdocs/javafx/scene/control/ListView.htmlで「fixedCellSize」を参照してください。

は、一般的に、細胞は、私は「[F]何とかスタイリングやトリッキーなものは厄介であるから、などの行の高さ、境界線の幅を、アウトiguringことに同意しながら、だから、

...は24pxの周りですが、おそらく唯一の方法へそれは真実かもしれません。正式な文書でバックアップされていることを前提とした作業は、始めるのに適しており、ListView(Java 7を使用しています)のテストでうまくいくリストになるようです。

+2

そのサイズは、スタイルシート、ルック・アンド・フィール、プラットフォーム(アンドロイド?)などに基づいて異なるように直接設定することも、デフォルトが存在する場合でもカウントするものではありません。 – mentics

+0

それはこれまでに変更が可能なデフォルトを持つものに当てはまりますが、最初にデフォルトが何であったかを知るユーティリティを削除しません。 –

3

あなたはそのために探しています:

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

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

5

私はポール・マーシャルの答えはObservableListの大きさを表す数値JFXのプロパティを作成Bindings.sizeを使用したワンライナーにreductedできることを見出し:

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

リストセルの高さは悲しげにまだなければなりませんAFAIKをハードコードしました。

+0

itemListPropertyとは何ですか? – uesports135

+0

が見つかりました。私はmaxHeightPropertyを使用しなければならなかったが、 – uesports135

0

ListCellのサブクラスで高さ(倍精度)を設定しようとします。代わりにCSSまたはそのようないくつかの構文解析、InvalidationListenerを追加:たとえば、私のコード

@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)); 
    } 
} 
3

に私は、すべての非空のセルが同じ高さを持っているという仮定の下で動作しますが比較的容易なものの、まだ少しハック解決策を見つけましたあなたのlistView.getItems();最初にアイテムリストが空でなくなったときにの子を再帰的に調べ、ListCellのインスタンスが見つかるまでとし、cell.getHeight()の値を格納します。そのコードをPlatform.runLater()にラップして、ListViewのレイアウトが完了したら実行されるようにしてください。その高さを得たら、それにlistView.getItems().size()を掛けて、結果値(InvalidationListenerの中にある)でlistView.setMaxHeightと呼んでください。

+0

クール!このような。 – Mordechai

+0

実際には再帰は使用せず、単に 'lookup("。list-cell ")'とするだけです。 – Mordechai

0

@warakawaの回答に基づいて、私は解決策を見つけました。私たち皆知っているように、Listviewの実装は多くの頭痛を引き起こしています。このため、 "PREF_SIZE"(高さには400の定数があり、高さには幅が計算されます)の問題を修正する2つのクラスを書いています。私が書いたスキンクラスは、期待どおりにサイズを計算し、新しいプロパティ "fillWidth"が "true"に変更されたときに醜い水平バーを防止します。このプロパティは、セルをできるだけ水平方向に拡大させます。よろしく。

を使用でき

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

これはアプリケーションでどのように使用しますか? (特にシーンビルダの場合) – mrseanpaul81

+0

他のカスタムコンポーネントとして使用します。よろしく。 –

関連する問題

 関連する問題