Search code examples
javaswtscrolledcomposite

How to set the max height of ScrolledComposite in SWT


I have a ScrolledComposite with a button which creates a new button below, "on the next row". And every time I adapt the height of my composite with pack().

But now I want to set the maximum height so, that from a certain size the height of the window stays the same and I get a vertical scrollbar.


Solution

  • Calling pack() will always resize the control so that it can show its entire contents. Instead, the size of the scrolled composite should be managed by the layout of its parent. That is the whole purpose of the scrolled composite: showing the contained controls and offering scroll bars when needed.

    Use setMinSize() to control when scroll bars should be shown. The below example features a scrolled composite with a single button. Pushing the button will add another button. Note that after a button was added min size is recomputed in updateMinSize().

    public class DynamicScrolledComposite {
    
      public static void main( String[] args ) {
        Display display = new Display();
        Shell shell = new Shell( display );
        shell.setLayout( new FillLayout() );
        ScrolledComposite scrolledComposite = new ScrolledComposite( shell, SWT.H_SCROLL | SWT.V_SCROLL );
        scrolledComposite.setExpandVertical( true );
        scrolledComposite.setExpandHorizontal( true );
        scrolledComposite.addListener( SWT.Resize, event -> updateMinSize( scrolledComposite ) );
        Composite composite = new Composite( scrolledComposite, SWT.NONE );
        composite.setLayout( new GridLayout( 1, false ) );
        createButton( composite );
        scrolledComposite.setContent( composite );
        shell.setSize( 600, 300 );
        shell.open();
        while( !shell.isDisposed() ) {
          if( !display.readAndDispatch() )
            display.sleep();
        }
        display.dispose();
      }
    
      private static void updateMinSize( ScrolledComposite scrolledComposite ) {
        Rectangle clientArea = scrolledComposite.getClientArea();
        clientArea.width -= scrolledComposite.getVerticalBar().getSize().x;
        Point minSize = scrolledComposite.getContent().computeSize( clientArea.width, SWT.DEFAULT );
        scrolledComposite.setMinSize( minSize );
      }
    
      private static void createButton( Composite parent ) {
        Button button = new Button( parent, SWT.PUSH );
        button.setText( "Add another button" );
        button.addListener( SWT.Selection, new Listener() {
          @Override
          public void handleEvent( Event event ) {
            createButton( parent );
            ScrolledComposite scrolledComposite = ( ScrolledComposite )button.getParent().getParent();
            button.getParent().requestLayout();
            updateMinSize( scrolledComposite );
          }
        } );
      }
    }
    

    To learn more about the different content management strategies of the ScrolledComposite, see here: http://www.codeaffine.com/2016/03/01/swt-scrolledcomposite/