站内搜索: 请输入搜索关键词
当前页面: 图书首页 > SWT: The Standard Widget Toolkit

4.9 Repainting and Resizing - SWT: The Standard Widget Toolkit

Previous Section  < Day Day Up >  Next Section

4.9 Repainting and Resizing

When a control is resized to be larger, there is more space available for the control to display its content. Controls typically deal with this in two ways.

  1. They "spread out" the existing content to cover the new area.

  2. They leave the existing content where it was and draw more content in the new area.

If the control is going to spread out its contents, it needs to be notified that its entire client area must be repainted when the control is resized, either larger or smaller. This allows it to display all of its content in the new, correct places.

If the control is going to draw new content as it is resized to be larger but not change any of the previously visible content, it only needs to repaint the "backwards L" covering the newly visible area, as is shown by the white region in Figure 4.7. In this mode, when the control is resized to be smaller, no redrawing is required.

Figure 4.7.

graphics/04fig07.gif


Because it is better for a control to display too much when it is repainted than it is for it to paint only part of the needed area, the default behavior in SWT is to cause the entire area of the control to be redrawn each time it is resized. However, drawing too much can cause a control to flicker.

If you specify the SWT.NO_REDRAW_RESIZE style when creating a control,[12] when the control is resized larger, a paint event is generated that contains a GC whose clipping region has been set to a Region containing only the newly visible area. If you resize the control to be smaller, a paint event is not generated at all.

[12] SWT.NO_REDRAW_RESIZE and the other style bits that govern drawing are used with the classes Composite, Canvas, and Shell. All other classes use whatever strategy is implemented by the particular native control.

The following example code uses SWT.NO_REDRAW_RESIZE to generate Figure 4.7. The background color of the shell is set to gray before the shell is opened so that the first paint event will draw gray. After the shell is opened, an SWT.Paint listener is added that fills the entire client area in white. As you can see, when the shell is resized to be larger, the fill operation is clipped to the "backwards L."






public static void main(String[] args) {

    Display display = new Display();

    final Color white =

        display.getSystemColor(SWT.COLOR_WHITE);

    final Color gray =

        display.getSystemColor(SWT.COLOR_GRAY);

    int style = SWT.SHELL_TRIM | SWT.NO_REDRAW_RESIZE;

    final Shell shell = new Shell(display, style);

    shell.setBackground(gray);

    shell.setSize(200, 200);

    shell.open();

    shell.addListener(SWT.Paint, new Listener() {

        public void handleEvent(Event event) {

            GC gc = event.gc;

            gc.setBackground(white);

            gc.fillRectangle(shell.getClientArea());

        }

    });

    shell.setSize(250, 250);

    while (!shell.isDisposed()) {

        if (!display.readAndDispatch()) display.sleep();

    }

    display.dispose();

}


Why Isn't SWT.NO_REDRAW_RESIZE the Default?

Because there is no way of telling how a control will draw in advance, it is not possible to know whether the entire client area should be damaged when the control is resized. The choice is between drawing too much and possibly flickering or drawing too little, causing garbage to be drawn on the screen.


4.9.1 Using SWT.NO_REDRAW_RESIZE to Reduce Flicker

As was previously stated, if the graphics that you are drawing do not depend on the size of the control, redrawing the whole client area whenever the control is resized can cause areas that have not changed to flicker. For example, if your control draws a left-aligned list of strings, resizing the control to be larger should draw only those strings that intersect with the "backwards L." When the control is resized to be smaller, nothing needs to be drawn.

The following example uses SWT.NO_REDRAW_RESIZE to reduce the amount of drawing for a list of strings. Note that this example is very simple and could reduce the amount of drawing further by drawing only those strings that intersect with the client area. Figure 4.8 shows the list of strings. Try removing the SWT.NO_REDRAW_RESIZE to see the flicker.






public static void main(String[] args) {

    final String[] list = new String[128];

    for (int i = 0; i < list.length; i++) {

        list[i] = i + "-String-that-is-quite-long-" + i;

    }

    Display display = new Display();

    int style = SWT.SHELL_TRIM | SWT.NO_REDRAW_RESIZE;

    final Shell shell = new Shell(display, style);

    shell.addListener(SWT.Paint, new Listener() {

        public void handleEvent(Event event) {

            GC gc = event.gc;

            int height = gc.stringExtent("").y;

            for (int i = 0; i < list.length; i++) {

                gc.drawText(list[i], 2, i * height);

            }

        }

    });

    shell.setSize(200, 200);

    shell.open();

    while (!shell.isDisposed()) {

        if (!display.readAndDispatch()) display.sleep();

    }

    display.dispose();

}


Figure 4.8.

graphics/04fig08.gif


    Previous Section  < Day Day Up >  Next Section