SWT ScrolledComposite Explained

Home  >>  Eclipse  >>  SWT ScrolledComposite Explained

SWT ScrolledComposite Explained

On March 1, 2016, Posted by , In Eclipse, By ,,,, , With 6 Comments

Like a friend of mine once put it, SWTs ScrolledComposite is a nasty beast. And to some point, I do agree. This is likely the reason why there are so many questions asked about how to use this widget.

But it’s not only the authors of the ScrolledComposite to blame. When a piece of software doesn’t work the way you expect it to work, then … you curse … and try a little different … and curse differently … and ask Google for help … and (hopefully) find this lovely little post. Which tells you: RTFM! – ups, ehm, I mean of course take a look at the documentation.

And if you read the JavaDoc you will learn that there are two ways to use the ScrolledComposite and see corresponding sample code.

Two in One

The first way is suitable for fixed size content and will show scrollbars if the contained control cannot be fully seen and hide them otherwise.

Alternatively, if set up accordingly, the ScrolledComposite imitates the way a browser would work. The content will grow and shrink with the size of the ScrolledComposite – until the visible area is less than the specified minimum size. In the latter case, scrollbars will be shown, and the content never decreases below the minimum size.

The video shows the different operation modes side by side:

On the left side, the size of content remains the same while the window is enlarged and scrollbars vanish when no longer needed. On the right side, however, the initial windows size is smaller than the specified minimum size and therefore scrollbars appear. As the window grows larger, the content grows with the window.

Scrolling Fixed Content

To Set up the ScrolledComposite to show fixed content is really simple:

scrolledComposite = new ScrolledComposite( parent, SWT.H_SCROLL | SWT.V_SCROLL );
Label label = new Label( scrolledComposite, SWT.NONE );
label.setBackground( display.getSystemColor( SWT.COLOR_DARK_GREEN ) );
label.setSize( 400, 400 );
scrolledComposite.setContent( label );

Note that you need to explicitly specify the H_SCROLL and V_SCROLL style flags. Otherwise no scrollbars are created and the ScrolledComposite is of little use (more on scrollbars later).

The other noteworthy part of the snippet is where the content – a 400 x 400 px green label here – is created. The parent of the content must be the ScrolledComposite itself. If not you will see funny results. And finally, the ScrolledComposite must be told the content that it should manage with setContent().

The example demonstrates the simplest case in which the content is a single control. If however the content to scroll consists of multiple controls, they need to be wrapped into a Composite with a suitable layout like shown in contact details example.

The content control is assumed to be a direct child control of the ScrolledComposite. Though the ScrolledComposite does not prevent setting other controls, this is usually not what you want.

Fixed size content in this context does not mean that the content must or can not change its size. If that happens, the ScrolledComposite will adapt to the new size and show or hide scrollbars accordingly. The content, however, does not change its size if the ScrolledComposite it resized.

Scrolling Expanding Content

With a few additional lines, the above snippet can be extended to expand its content:

scrolledComposite.setExpandHorizontal( true );
scrolledComposite.setExpandVertical( true );
scrolledComposite.setMinSize( 250, 250 );

Afterwards, the ScrolledComposite will expand the content when resized and only show scrollbars if its size is reduced so that it is smaller than the minimum size. The SWT API offers further ways to set the minimum size. Either for the minimum width and height independently with setMinWidth() and setMinHeight(), or with setMinSize(Point).

It is legal to set the minimum size to zero (the default value) when expanding content. As a result, the content will shrink with no lower limit and no scrollbars will ever be shown.

These are the two primary modes of the ScrolledComposite: managing content of fixed size or expanding and reducing content.

Scrolling Vertically Only

Another use case that I have come across is to have a list of yet unknown length of items. Think of a lengthy contact details form with many lines each consisting of a label and an input field. The width of each line occupies as much space as there is but if the number if lines exceed the available height, it should be scrollable.

This video demonstrates a contact details form that scrolls vertically:

With a little tweak, the above shown expanding ScrolledComposite can be extended to scroll only vertically. The key change is to set the minimum size dynamically. Whenever the ScrolledComposite changes its size, the minimum width of the content is set to the available width of the ScrolledComposite.

The code to accomplish the described behavior is rather simple:

scrolledComposite.addListener( SWT.Resize, event -> {
  int width = scrolledComposite.getClientArea().width;
  scrolledComposite.setMinSize( parent.computeSize( width, SWT.DEFAULT ) );
} );

The resize listener queries the available space of the ScrolledComposite with getClientArea()
and computes the necessary size for the content given the client areas width. Finally the resulting size is set as the minimum size of the ScrolledComposite.

In this example, the appearance of the content is governed by a two-column layout. The label column is as wide as necessary to show the longest label, and the input field column uses the remaining width. Each row, in turn, uses the optimal height (i.e. is as high as necessary to show a single-lined input field).

Even though I haven’t seen a real-world use case, this very approach would also work when expanding horizontally.

Computing the Preferred Size for a ScrolledComposite
There is nothing more saddening than to see an application that is designed with a single screen resolution or font size or color scheme (or all of them) in mind. To avoid this, the contact details form uses an adaptive strategy to compute its initial size.

As the content consists of repeating items (labeled input fields here), the size of a single item is taken as measuring unit. The number of items here is a figure gained from evidence but could be the (limited) number of rows obtained from a data source in other cases.

The formula itself is simple:

numberOfItems = 10
initialHeight = numberOfItems * ( itemHeight + spacing )

A further refinement would be to check the resulting height against the screen size and reduce it if necessary.

The resulting layout scales well across different platforms, screen resolutions, and font settings. If this caught your interest, you may also want to read Responsive UIs with Eclipse and SWT.

Vertical and Horizontal ScrollBar

To get hold of the scrollbars use getVerticalBar() and getHorizontalBar() respectively. As seen in the snippets, the V_SCROLL and H_SCROLL style flags need to be specified in order to have vertical and/or horizontal scrollbars created. If the respective style flag is omitted, no scrollbar is created and getVerticalBar() or getHorizontalBar() will return null.

Existing scrollbars, however, can be shown or hidden, enabled or disabled anytime. By default, the ScrolledComposite shows scrollbars only when necessary but with setAlwaysShowScrollBars() this behavior can be changed to always show scrollbars. Therefore, you would usually want to have both scrollbars created and let the ScrolledComposite decide when to show or hide individual bars.

In general, be aware that scrollbars are managed by the ScrolledComposite. Hence, it is safe to query their state, but manipulating the properties will most likely interfere with the ScrolledComposite’s view of things.

To change the position of scrollbars to bring certain parts of the content into view, use the designated methods discussed below.

The only exception of the above said may be the enabled state of scrollbars. If this is truly desired, it should be safe to call setEnabled().

Scrolling into View

The ScrolledComposite has several methods to change the scrollbar position. The most basic is setOrigin(). It scrolls the content control so that the specified point in the content is in the top left corner. The desired position can be given as separate x and y coordinates or as a Point. And consequently there is a getOrigin() method that returns the point that currently appears in the top left corner.

To spare clients some coordinate mapping, there is showControl() which builds on setOrigin() and scrolls the content so that the given control is visible.

And if the focused control should always be visible, the ScrolledComposite can be advised with setShowFocusedControl() to scroll automatically the focused control into view.

Concluding SWT ScrolledComposite

Indeed, the ScrolledComposite isn’t the most intuitive widget in the SWT collection, and I hope that the recipes presented here will help to get along with it better. The use cases discussed here are those that I came across mostly so far. However, I would be curious to learn further uses, and if you would like to share yours, please leave a comment.

The shown snippets are extracts of small, ready to run example programs, that can be found here:

And last but not least I would like to point out that all concepts and code shown here not only apply to SWT but equally well run in a browser with Eclipse RAP. You can even use this RAP online demo to change various flags and properties and see their effect immediately.

Follow me

Rüdiger Herrmann

Routined programmer, team lead, presenter, blog writer, and convinced open source contributor with two decades experience in the field.

Strong focus on quality backed up by agile methods like test driven development, modularization, pair programming, clean code, continuous integration.

Specialized in Java with JEE, REST, OSGi, RCP, RAP and building developer tools based on the Eclipse IDE (or any other platform if an opportunity arises).
Follow me

Latest posts by Rüdiger Herrmann (see all)

6 Comments so far:

  1. Suhel Khan says:

    Awesome explanation. Thanks a lot.

  2. Every time I used ScrolledComposite in the past I have spent half a day getting it to work.
    This time, after reading this post, it took me 10 minutes. Very well explained. This should be included in the official SWT documentation!

  3. Stefan Haustein says:

    In a vertical scrolling case where the minimum width mainly depends on external constraints (e.g. the window size), it might be simpler and cleaner to setExpandHorizonal(true) and setExpandVertical(false), avoiding the resize listener. This is probably also closer to what people would expect for a “browser-like” behavior (compared to the right panel in the first example).

    In general, the main problem with setting expand to true seems to be that in this case the ScrolledComposite builtin layout manager only considers the minimum size explicitly set on ScrollledComposite and the current size of the ScrolledComposite, disregarding the “actual” size of the contents. I assume the intention behind this (not very intuitive) behavior is to avoid a circular dependency in the case where the content doesn’t have a layout manager.

    While this important detail is actually documented in the Javadoc, it probably should have a stronger warning that setExpandXxx changes the base for content size calculations from the actual content size to the values explicitly set via setMinWidth / setMinHeight. It doesn’t really help that the names of these methods sound like they would apply to the scroll composite itself — opposed to its content.

    • Rüdiger Herrmann says:

      Thank you very much for sharing your insights.

      After applying your suggestions to the VerticallyScrolledForm I find it worth mentioning that, of course, the height of the content control need to be set in this case.

      And the resize listener would still be necessary to update the minWidth after said external constraints (e.g. the window size) have changed.

      • Stefan Haustein says:

        Ooops, sorry for the incorrect comment — I hadn’t realized that I was using a hacked version that implicitly computes the content size if expanding is not set.
        It looks like in this specific example, the listener would not be needed, but that’s just because the content height does not depend on the available width, which is not necessarily the case in general (e.g. if there is a wrapping text block that needs to be adjusted to the width).

        • Rüdiger Herrmann says:

          Thank you again for your comment. To summarize, in the “browser-like” use case, the resize listener and scrolledComposite.setExpandVertical( true ) is not necessary if the height of the content control is known in advance and does not depend on the available width

          I hope to find some time soon, to update the article accordingly.

Leave a Reply

Your email address will not be published. Required fields are marked *