tags:

views:

2509

answers:

2

I'm writing an app and our designer's want to user gradient's for some of the backgrounds on a few of our composite's.

I wrote the following code:

composite.addListener (SWT.Paint, new Listener () {
 public void handleEvent (Event e) {
   GC gc = e.gc;
   Rectangle rect = composite.getClientArea ();
   Color color1 = new Color (display, 0, 0, 0);
   Color color2 = new Color (display, 255, 255, 255);
   gc.setForeground(color1);
   gc.setBackground(color2);
   gc.fillGradientRectangle (rect.x, rect.y, rect.width, rect.height , true);

  }
 });

This draw's the gradient fine on the composite, but we have Label/CLabel's, Canvas's and Link's on top of the composite.

In these area's the background is just the plain gray you get when drawing and empty canvas.

I've tried forcing the Label's to inherit the background like so:

label.setBackgroundMode(SWT.INHERIT_DEFAULT) //SWT.INHERIT_FORCE Doesn't work either

But this leaves me with the same default gray and no gradient behind the components on top of the Composite.

Any suggestion's for getting the gradient to be the background of each element?

I wouldn't be apposed to drawing the Gradient onto a gc with an imagine supplied and then setting the background to that Image. However that method just hasn't been working at all, composite or any of it's elements.

Also it's not possible for me to set the gradient individually to my knowledge.We want the whole composite to be one uniform flowing gradient.

[edit] I uploaded an example upto twitpic here.

Thanks,

Brian Gianforcaro

A: 
qualidafial
This was a good idea, but it draws on the actual gc of the the control, so any text or anything on the control will be obliterated
Brian Gianforcaro
+6  A: 

Use composite.setBackgroundMode(SWT.INHERIT_DEFAULT), but do not paint the composite directly - paint an image and set it as the background image using composite.setBackgroundImage(Image). Unless I'm missing a trick, this means you only have to regenerate the image when the composite is resized too.

You should be able to cut'n'paste this code as is to see what I mean:

import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.widgets.*;

/**
 * SWT composite with transparent label
 * 
 * @author McDowell
 */
public class Sweet {

    private Image imageGradient;
    private Label label;
    private Composite composite;

    private void createComponents(Shell parent) {
        composite = new Composite(parent, SWT.NONE);
        composite.addListener(SWT.Resize, new Listener() {
            public void handleEvent(Event e) {
                changeImage();
            }
        });
        composite.setLayout(new FormLayout());
        composite.setBackgroundMode(SWT.INHERIT_DEFAULT);

        label = new Label(composite, SWT.None);
        label.setText("Hello, World!");
    }

    private void changeImage() {
        Image oldImage = imageGradient;

        Display display = composite.getDisplay();
        Rectangle rect = composite.getClientArea();
        imageGradient = new Image(display, rect.width, rect.height);
        GC gc = new GC(imageGradient);
        try {
            Color color1 = new Color(display, 200, 200, 255);
            try {
                Color color2 = new Color(display, 255, 255, 255);
                try {
                    gc.setForeground(color1);
                    gc.setBackground(color2);
                    gc.fillGradientRectangle(rect.x, rect.y, rect.width,
                            rect.height, true);
                } finally {
                    color2.dispose();
                }
            } finally {
                color1.dispose();
            }
        } finally {
            gc.dispose();
        }
        composite.setBackgroundImage(imageGradient);

        if (oldImage != null) {
            oldImage.dispose();
        }
    }

    private void openShell(Display display) {
        Shell shell = new Shell(display);
        try {
            shell.setSize(200, 100);
            shell.setLayout(new FillLayout());
            createComponents(shell);
            shell.open();
            while (!shell.isDisposed()) {
                if (!display.readAndDispatch()) {
                    display.sleep();
                }
            }
        } finally {
            if (!shell.isDisposed()) {
                shell.dispose();
            }
        }
    }

    public void run() {
        Display display = Display.getDefault();
        try {
            openShell(display);
        } finally {
            display.dispose();
        }
    }

    public void dispose() {
        if (imageGradient != null) {
            imageGradient.dispose();
        }
    }

    public static void main(String[] args) {
        Sweet sweet = new Sweet();
        try {
            sweet.run();
        } finally {
            sweet.dispose();
        }
    }

}
McDowell
With a little bit of modification and nudging this worked wonderfully. Thank you!
Brian Gianforcaro