7

So, basically, I'm trying to achieve this a scrollable set of components with spacing etc. and the ability to add more components. The list of components are custom anchorpane components.

Here's an example that I got working: enter image description here

The problem is that that uses a gridpane inside of a scrollpane and for some reason the gridpane does not fill the width of the scrollpane at all. So, if I resize, everything stays where it is instead of stretching inside the gridpane columns. Also, if I were to stick to a gridpane (over a tilepane which seems to work better except when the components float next to each other despite the orientation being vertical and prefcolumns being 1), how would I add more rows? The idea of this is to list github repos in a nice, UX pleasing, fashion.

Thanks for any insight. Also: those repos aren't mine - I have none and a guy on a website made that (it's not well made so don't compare me to him lol).

user3530525
  • 691
  • 3
  • 8
  • 20
  • 2
    How about [Enrich your List UI by using the MediaListCell](http://www.guigarage.com/2014/09/enrich-list-ui-using-medialistcell/). Otherwise provide some code. – Roland May 07 '15 at 15:24
  • @Roland - Currently I'm prototyping everything in scene builder but I think I may have to start making the custom components w/ code soon to get the functionality that I would like. That link is interesting though, I'll use that for another part of the program. Right now, I'm just looking for a purely FXML based solution. – user3530525 May 07 '15 at 15:29
  • 2
    Looks like you could do that simply with a `VBox` in a `ScrollPane`. `fillWidth="true"` for the `VBox` and `fitToWidth="true"` for the `ScrollPane`. If you want a `GridPane` use the `columnConstraints` to control the width. But, create a simple example and post some code if you want a more complete answer. – James_D May 07 '15 at 15:51
  • @James_D Your idea works great. Is there anyway for it to be possible to make the components in the VBox (anchorpanes) stretch to fit the width of the VBox? – user3530525 May 07 '15 at 16:23
  • 1
    Setting `fitToWidth` to `true` on the scroll pane should be enough. – James_D May 07 '15 at 17:28

1 Answers1

9

This looks like you should use a VBox to hold your AnchorPanes and put them in a ScrollPane. Set fitToWidth to true on the ScrollPane and it should force the anchor panes to take up the whole width (and no more) of the scroll pane's viewport, assuming you don't change the maxWidth property on the AnchorPane from its default.

Mocked-up example (which can easily be done in FXML if you prefer):

import java.util.Random;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ScrollPane;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class ScrollingVBox extends Application {


    @Override
    public void start(Stage primaryStage) {

        final Random rng = new Random();
        VBox content = new VBox(5);
        ScrollPane scroller = new ScrollPane(content);
        scroller.setFitToWidth(true);

        Button addButton = new Button("Add");
        addButton.setOnAction(e -> {
            AnchorPane anchorPane = new AnchorPane();
            String style = String.format("-fx-background: rgb(%d, %d, %d);"+
                    "-fx-background-color: -fx-background;",
                    rng.nextInt(256),
                    rng.nextInt(256),
                    rng.nextInt(256));
            anchorPane.setStyle(style);
            Label label = new Label("Pane "+(content.getChildren().size()+1));
            AnchorPane.setLeftAnchor(label, 5.0);
            AnchorPane.setTopAnchor(label, 5.0);
            Button button = new Button("Remove");
            button.setOnAction(evt -> content.getChildren().remove(anchorPane));
            AnchorPane.setRightAnchor(button, 5.0);
            AnchorPane.setTopAnchor(button, 5.0);
            AnchorPane.setBottomAnchor(button, 5.0);
            anchorPane.getChildren().addAll(label, button);
            content.getChildren().add(anchorPane);
        });

        Scene scene = new Scene(new BorderPane(scroller, null, null, addButton, null), 400, 400);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}

Another solution might be to use a ListView. (This would be preferable if you had many items to display.) Create a class representing the items you are displaying in each AnchorPane and a custom list cell to display them.

James_D
  • 201,275
  • 16
  • 291
  • 322