2

Embedded containers with scrollbars

Above, I have added a screen shot - now that I can add images. The bottom of the screen shot shows the edge of the scene (with no scrollbar on outer container 2).

This scene may become too busy - but I am attempting to use nested scroll panes which contain either a FlowPane or VBox. I am defining "inner containers" which is a VBox and includes a textfield and scroll pane which has a flow pane as it's content. The flow pane loads a number of "status blocks". The scroll pane for the inner containers seems to be working okay. Below is a code snippet from the inner container:

public class InnerContainer extends VBox
{
  // Declare the various parts of the inner container
  private TextField m_icName = null;     // Name of the inner container
  private ScrollPane m_icScroll = null; 

  private FlowPane m_icFlow = null;  // Holds the status blocks

  // List of status blocks in this inner container
  private ArrayList<StatusBlock> m_statBlockList = null;

  /******************************************************************
  *  Create the containers and controls used by the inner container *
  ******************************************************************/

  public InnerContainer()
  {
    m_statBlockList = new ArrayList<>();  // Set up list of status blocks  
    setMinSize(200.0, 170.0);      
    setPrefSize(200, 170);         
    setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
    setPadding(new Insets(5, 5, 5, 5));

    m_icName = new TextField();
    m_icName.setMaxWidth(Double.MAX_VALUE);

    m_icScroll = new ScrollPane();
    m_icScroll.setFitToWidth(true);
    m_icScroll.setFitToHeight(true);
    m_icScroll.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
    VBox.setVgrow(m_icScroll, Priority.ALWAYS);

    m_icFlow = new FlowPane();

    m_icFlow.setPrefWrapLength(650.0);  // This is the "wrap" point

    m_icFlow.setVgap(5);
    m_icFlow.setHgap(5);

    m_icFlow.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);

    m_icScroll.setContent(m_icFlow);

    // Add the elements to the vbox
    getChildren().addAll(m_icName, m_icScroll);   

    VBox.setVgrow(this, Priority.ALWAYS);

I've been unable to get the scroll bars to work properly for the outer containers. If I add inner containers the outer container just keeps growing and I can never get the scroll bar to show up (even if it exceeds the size of the screen). I suspect I am having trouble correctly computing the size of the content of the outer container. The outer container is a VBox which contains a text field and a scrollpane which has content of a VBox. The final VBox can consist of one to many inner containers.

Here is a code snippet from the outer container:

public class OuterContainer extends VBox
{

  // Declare the various parts of the outer container
  private TextField m_ocName = null;     // Name of the outer container
  private ScrollPane m_ocScroll = null;
  private VBox m_ocMainVBox = null;
  private ArrayList<InnerContainer> m_innerContList = null;

  public OuterContainer()
  {
    // Setup the inner container list
    m_innerContList = new ArrayList<>();

    setSpacing(8);
    setPrefSize(USE_COMPUTED_SIZE, USE_COMPUTED_SIZE);      
    setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
    setPadding(new Insets(5, 5, 5, 5));

    m_ocName = new TextField();
    m_ocName.setMaxWidth(Double.MAX_VALUE);

    m_ocScroll = new ScrollPane();
    m_ocScroll.setFitToWidth(true);
    m_ocScroll.setFitToHeight(true);
    m_ocScroll.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
    VBox.setVgrow(m_ocScroll, Priority.ALWAYS);   

    m_ocMainVBox = new VBox();
    m_ocMainVBox.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
    VBox.setVgrow(m_ocMainVBox, Priority.ALWAYS);   
    m_ocMainVBox.setSpacing(5);
    m_ocMainVBox.setMinSize(1.0, 1.0);

    m_ocScroll.setContent(m_ocMainVBox);

    // Add the elements to the top vbox
    getChildren().addAll(m_ocName, m_ocScroll);

    VBox.setVgrow(this, Priority.ALWAYS);

There is a final outer class which also should potentially have a scrollbar. It also isn't working correctly, but I suspect the issue is similar to what I am asking for help with here.

Thanks in advance for any help.

  • If the outer container is supposed to have a ScrollBar, why do you extend a `VBox` instead of `ScrollPane`? – ItachiUchiha Mar 18 '15 at 17:20
  • The reason it extends VBox instead of ScrollPane is that the outer container includes a textfield (used for naming the container) and the scrollpane. – Dale Hooper Mar 18 '15 at 18:25
  • Do you have multiple TextField and ScrollPane combination inside one VBox? When you say, *"I can never get the scroll bar to show up(even if it exceeds the size of the screen)"*, do you want to show scrollbar's on the VBox ? – ItachiUchiha Mar 18 '15 at 18:40
  • The outer container contains a single TextField and a single ScrollPane. The contents of the ScrollPane is a VBox (which can hold many inner containers). As you mention, I can never get the scroll bar for the scroll pane to show up - no matter how large the contained VBox gets. I've struggled to figure out why. My suspicion is that I need to use a bind() method with the height property, but I haven't been able to figure out what it should be bound to. – Dale Hooper Mar 18 '15 at 19:54
  • Can you post an image now? – James_D Mar 18 '15 at 20:05
  • Added a screen shot - thanks for the suggestion. – Dale Hooper Mar 18 '15 at 21:05

1 Answers1

0

I've abandoned trying to use three scrollbars and will instead use a single scrollbar. However, I believe the root issue was addressed in:

Java FX scales the parent based on the content size

The size of the FlowPane or VBox used as the content of the ScrollPane keeps growing as the size of the content grows. This also causes the height of the scrollpane to grow. To resolve this, I am now basing the pref height of the scroll pane on the height of the stage. I've also added a change listener that looks for changes to the stage height property. It is similar to the following code snippet:

m_dashScroll.setPrefHeight(TopClass.getStage().getHeight() - DECORATION_OFFSET);

TopClass.getStage().heightProperty().addListener(new ChangeListener<Number>()
{
  @Override
  public void changed(ObservableValue<? extends Number> ov,
                      Number oldVal, Number newVal)
  {
    m_dashScroll.setPrefHeight(newVal.doubleValue() - DECORATION_OFFSET);
  }
});

This required a static reference to the stage, so I would be interested if there are better ways to do this. [Also, I could use a lambda here if desired.]

Community
  • 1
  • 1