Search code examples
javaswingjframelayout-managerjscrollpane

Unreliable Container width when using JScrollPane


I made a custom LayoutManager to render components in uniform squares in the space provided, and it does that by using the following method:

    @Override
    public void layoutContainer(Container parent) {

        if(parent.getWidth() == 0) {
            return;
        }

        int columns = parent.getWidth() / gridSizeWidth;
        
        
        int x = 0, y = 0;
        for(int i = 0; i < parent.getComponentCount(); i++) {
            Component comp = parent.getComponent(i);

            comp.setBounds(x * gridSizeWidth, y * gridSizeHeight, gridSizeWidth, gridSizeHeight);
            
            if(++x == columns) {
                x = 0;
                y++;
            }

        }
        System.out.println(parent.getClass().getSimpleName() + ": " + parent.getWidth());

    }

This code works as intended when applied directly to the JFrame, but if I try to insert it inside of a JScrollPane, then it very quickly falls apart.

When it is only added to the JFrame and looks correct, the console reads:

TileScroller: 422

However, when adding it into a JScrollPane...

TileScroller: 419
TileScroller: 26816
TileScroller: 1716224
TileScroller: 109838336
TileScroller: 419
TileScroller: 26816
TileScroller: 1716224
TileScroller: 109838336
TileScroller: 419
...

It repeats this very quickly and causes a flicker effect from changing the layout so rapidly. As far as I can see, it is correctly placing each component at the correct spot for each size, but the issue is that the size is fluctuating.

Here is my code for creating the JScrollPane.

        JPanel modeIndividualTile = new JPanel();
        JScrollPane tileScroller = new JScrollPane(tileSelector = new TileScroller(creator),
                ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
                ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
        tileScroller.getVerticalScrollBar().setUnitIncrement(8);

        modeIndividualTile.add(tileScroller);

        // Custom layout manager that renders everything relatively to the designated values below. (20,65) will render at x=20% of width, y=65% of height.
        rl.addComponent(frame, tileScroller, 20, 65, 80, 98);

What could be the cause of this, and how could I prevent it?


Solution

  • The problem was because of an inpromper implementation of preferredLayoutSize and minimumLayoutSize. Properly using these methods fixed it.