|
|
< Day Day Up > |
|
4.9 Repainting and ResizingWhen 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.
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.
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.
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();
}
4.9.1 Using SWT.NO_REDRAW_RESIZE to Reduce FlickerAs 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.
|
|
|
< Day Day Up > |
|