2016-07-24 7 views
0

グリッド内にアーティストとアルバムを表示するこの音楽再生アプリがあります。私はListViewとカスタムListCellを使ってこのグリッドを作成しました。ただし、高さが画面のサイズに応じて3行または4行をレンダリングするのに十分な場合でも、ListViewは初期化されたときに2つ以上のセルを表示しません。リストビューは、最初の2つのセルのうちの1つが上にホバリングされたとき、残りのセルをレンダリングします。下のリンクを見て、実際の問題を見てください。JavaFX ListViewがビューポートを埋めるのに十分なセルを表示しない

demo of the issue

私は、リストビューの高さを確認したのだが、確かにその親を埋めるために拡大しているので、私はListViewコントロールは、細胞をレンダリングする必要があることを決定する方法で起こっているファンキーなものがあると信じて。私は、それが根本的な問題である場合、ListViewに正しい数のセルを描画させる方法を発見したいと思っています。あるいは、コードに間違いがあると、それにも少し光を当てるのは素晴らしいことです。私は私のコントローラと私のカスタムListCellのコードを以下に掲載しました。

リストビューを初期化コントローラ:

public class ArtistsController implements Initializable { 

    @FXML 
    private ListView<ArrayList<Artist>> grid; 

    @Override 
    public void initialize(URL location, ResourceBundle resources) { 

     List<Artist> artists = Library.getArtists(); 
     Collections.sort(artists); 

     grid.setCellFactory(x -> new ArtistListCell<>()); 

     ObservableList<ArrayList<Artist>> rows = FXCollections.observableArrayList(); 
     ArrayList<Artist> row = new ArrayList<>(); 
     int col; 

     for (int i = 0; i < artists.size(); i++) { 
      col = i % 5; 
      if (col == 0) { 
       row = new ArrayList<>(); 
       rows.add(row); 
      } 
      row.add(artists.get(i)); 
     } 

     grid.setItems(rows); 
    } 
} 

カスタムのlistcell:

public class ArtistListCell<T extends ArrayList<Artist>> extends ListCell<T> { 

    private T item; 

    public ArtistListCell() { 
     this.getStyleClass().setAll("artist-list-cell"); 
    } 

    @Override 
    protected void updateItem(T item, boolean empty) { 
     super.updateItem(item, empty); 
     if (empty || item == null) { 
      setText(null); 
      setGraphic(null); 
     } else if (!item.equals(this.item)) { 
      this.item = item; 
      HBox row = new HBox(); 
      item.forEach(artist -> { 
       VBox cell = createCell(artist); 
       row.getChildren().add(cell); 
      }); 
      setGraphic(row); 
     } 
    } 

    private VBox createCell(Artist artist) { 

     VBox cell = new VBox(); 
     Label title = new Label(artist.getTitle()); 
     ImageView image = new ImageView(artist.getArtistImage()); 
     image.imageProperty().bind(artist.artistImageProperty()); 
     VBox imageBox = new VBox(); 

     title.setTextOverrun(OverrunStyle.CLIP); 
     title.setWrapText(true); 
     title.setPadding(new Insets(10, 0, 10, 0)); 
     title.setAlignment(Pos.TOP_LEFT); 
     title.setPrefHeight(66); 
     title.prefWidthProperty().bind(this.widthProperty().subtract(102).divide(5)); 

     image.fitWidthProperty().bind(this.widthProperty().subtract(102).divide(5)); 
     image.fitHeightProperty().bind(this.widthProperty().subtract(102).divide(5)); 
     image.setPreserveRatio(true); 
     image.setSmooth(true); 

     imageBox.prefWidthProperty().bind(this.widthProperty().subtract(102).divide(5)); 
     imageBox.prefHeightProperty().bind(this.widthProperty().subtract(102).divide(5)); 
     imageBox.setAlignment(Pos.CENTER); 
     imageBox.getChildren().add(image); 

     cell.getChildren().addAll(imageBox, title); 
     cell.setPadding(new Insets(10, 10, 0, 10)); 
     cell.getStyleClass().add("artist-cell"); 
     cell.setAlignment(Pos.CENTER); 

     cell.setOnMouseClicked(event -> { 
      // do something 
     }); 

     cell.setOnDragDetected(event -> { 
      // do something 
     }); 

     return cell; 
    } 
} 
+0

イメージの大きさはどのくらいですか、どのようにイメージを読み込みますか? – fabian

+0

これらは300x300ピクセルの.jpgで、それぞれ約20KBです。それらは次のようにロードされています:Image image = new Image( "file path goes here"); – naquilleosheal

+0

それにもかかわらず、イメージを読み込むことに問題があります。シーンを表示する前に画像がロードされていることを確認してください。それらをマップに格納し、 'createCell'でそれらを取得し、これが動作を変更するかどうかをチェックします。 (私は 'createCell'でイメージを作成していると思います)。さらに、' createCell'メソッドが大きくない場合は、それを追加するか(問題を再現するための単純化されたバージョン)、質問? – fabian

答えて

0

私がテストを一緒に入れて、アーティストのための単一の静止画像を使用してこの問題を経験しました。私がListCellの行ビルドを単純な四角形に置き換えてもうまくいくので、ボトルネックはHBox/VBoxセルを構築しているようです。

grid.setItemsの後にsetCellFactoryへの呼び出しを解決しているようです。

grid.setItems(rows); 
grid.setCellFactory(x -> new ArtistListCell<>()); 

その周りに他の方法は、それが適切に計算するのに必要なすべての情報を持っていないのに対し、私は、この方法は、別のレイアウトパスを要求していることをやって言うのだろうか?

時間がかかる場合は、適切な画像読み込みを使用して異なる結果が得られることがあります。もしそうなら、あなたはまだプレースホルダ画像を使っていますか?

+0

これは私の問題を解決しませんでしたが、ImageViewのfitWidthPropertyとfitHeightPropertyがバインドされているcreateCellの2行に問題を絞りました。これらのいずれかをsetFitWidthまたはsetFitHeightに置き換えると、リストビューがより多くのセルをロードするように見えます。しかし、これらのバインディングが追加され、グリッドのサイズを変更できるようになりました – naquilleosheal

+0

おそらく、HBoxのサイズをArtistListCellのサイズにバインドしてから、VBoxセルをHBoxのサイズにバインドしてみてください。チェーンのどこかをスキップしているので、値がバインディングで更新されることはありません。 – Geoff

関連する問題