Search code examples
javaswingjscrollpanespringlayout

JScrollBar Layout Manager and SpringLayout Manager not working together


public void createSpringLayout(SpringLayout spring, JLabel label, JScrollPane scrollPane, JPanel buttonPanel) {
    spring.putConstraint(SpringLayout.NORTH, label, 10, SpringLayout.NORTH, this);
    spring.putConstraint(SpringLayout.WEST, label, 10, SpringLayout.WEST, this);

    spring.putConstraint(SpringLayout.NORTH, scrollPane, 10, SpringLayout.SOUTH, label);
    spring.putConstraint(SpringLayout.WEST, scrollPane, 0, SpringLayout.WEST, label);
    spring.putConstraint(SpringLayout.EAST, scrollPane, -10, SpringLayout.EAST, this);

    spring.putConstraint(SpringLayout.NORTH, buttonPanel, Spring.constant(10, 30, 30), SpringLayout.SOUTH, scrollPane);

    spring.putConstraint(SpringLayout.SOUTH, buttonPanel, -10, SpringLayout.SOUTH, this);
    spring.putConstraint(SpringLayout.WEST, buttonPanel, 0, SpringLayout.WEST, label);
}

This is what happens

The two Jpanels with all the stuff on them are using the same superclass for better looks. However as you can see if the contents of the scrollpane are to wide the scrollpane just uses extra space in the bottom to create a horizontal scrollbar. Even if I tell the Springlayout that the spring between the scrollpane and the buttonPanel can be between 10 and 30.

I think that first the SpringLayoutManager is called to layout its components and then the ScrollPane comes along and notices that its displayed Components do not fit in the Viewport and creates a Scrollbar, which the SpringLayoutManager is unaware of.

I can't find any solution tha tell the ScrollPane beforehand to calculate its needed Size or for it to just dont use more Space than it has from the beginning.


Solution

  • Do not pass negative numbers to putConstraint.

    From the documentation of putConstraint:

    Links edge e1 of component c1 to edge e2 of component c2, with a fixed distance between the edges.

    The pad value is not an absolute pixel offset, it is the amount of padding (the distance) between the component and the linked edge. It should always be positive.

    The same javadoc also describes the pad parameter as:

    pad - the fixed distance between dependent and anchor

    SpringLayout is complex, which means it’s easy to make mistakes with it. You can easily accomplish the same layout with a BorderLayout:

    setLayout(new BorderLayout());
    add(label, BorderLayout.PAGE_START);
    add(scrollPane, BorderLayout.CENTER);
    add(buttonPanel, BorderLayout.PAGE_END);
    
    label.setBorder(BorderFactory.createEmptyBorder(0, 0, 10, 0));
    buttonPanel.setBorder(BorderFactory.createEmptyBorder(10, 0, 0, 0));
    this.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));