Mark Mark - 1 month ago 6
Java Question

How to make a ListView<ImageView> not take more space than it needs?

I made a

ListView<ImageView>
with some image

import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Orientation;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.ListView;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.stage.Stage;

public class MyApp extends Application {

@Override
public void start(Stage stage) throws Exception {

Image img = new Image("main/img.png");
ObservableList<ImageView> list = FXCollections.observableArrayList();
for (int i = 0; i < 4; i++) {
ImageView iView = new ImageView(img);
list.add(iView);
}

ListView<ImageView> listView = new ListView<>(list);
listView.setOrientation(Orientation.HORIZONTAL);

Group root = new Group(listView);
Scene scene = new Scene(root, 500, 500);
stage.setScene(scene);
stage.sizeToScene();
stage.show();
}

public static void main(String[] args) throws Exception {

launch(args);
}
}


enter image description here

but here is what it looks like

enter image description here

I want the image to cover each cell completely - no insets, no padding, no scrollbar. Just a border between them.

i wanted to bind the
heightProperty
of the list view but it's read-only. The image view also doesn't have size properties but i think it's the cell that's taking the space and not the image view.

I also tried to add a
Pane
like this:

Image img = new Image("main/img.png");
ObservableList<Pane> list = FXCollections.observableArrayList();
for (int i = 0; i < 4; i++) {
ImageView iView = new ImageView(img);
Pane pane = new BorderPane(iView);
pane.setStyle("-fx-background-color: yellow;");
list.add(pane);
}

ListView<Pane> listView = new ListView<>(list);
listView.setOrientation(Orientation.HORIZONTAL);


which gives this result

enter image description here

and also a renderer

list.setCellFactory((ListView<ImageView> l) -> new FitCell());


but you can't bind the cell's properties either. How do i do this without setting the height and width manually?

Answer

It doesn't really sound like you want a ListView at all. Put the ImageViews in a HBox, and wrap the HBox in a ScrollPane. You can make the scroll pane pannable and set the scroll bar policy as needed. This gives you full control over the layout, etc, without having to worry about the complexity of virtualized cells.

E.g.

HBox hbox = new HBox();
Image img = new Image("main/img.png");
for (int i = 0; i < 4; i++) {
    ImageView iView = new ImageView(img);
    Pane pane = new StackPane(iView);
    pane.setStyle("-fx-background-color: yellow;");
    hbox.getChildren().add(pane);
}

ScrollPane scroller = new ScrollPane(hbox);
scroller.setPannable(true);
scroller.setFitToHeight(true);
scroller.setHbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);

Group root = new Group(scroller);

// ...

You might need to set other styles on the pane, e.g. padding and borders, etc, but this should give you enough to get what you want.

Comments