如何使标签在SWT中继承Composite的GC

时间:2023-01-07 23:08:05

I'm writing an app and our designers want to use gradients for some of the backgrounds on a few of our composites.

我正在编写一个应用程序,我们的设计师希望在我们的一些复合材料上使用渐变来表示某些背景。

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 draws the gradient fine on the composite, but we have Label/CLabels, Canvases and Links on top of the composite.

这会在复合材料上绘制渐变,但我们在复合材料上面有Label / CLabels,Canvases和Links。

In these areas, the background is just the plain gray you get when drawing an empty canvas.

在这些区域中,背景只是绘制空白画布时的纯灰色。

I've tried forcing the Labels 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.

但是这给我留下了相同的默认灰色,并且在Composite顶部的组件后面没有渐变。

Any suggestions for getting the gradient to be the background of each element?

有关使渐变成为每个元素背景的建议吗?

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

我不反对将Gradient绘制到带有图像的gc上,然后将背景设置为该Image。然而,该方法根本没有工作,复合或其任何元素。

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.

[edit]我在这里上传了一个例子到twitpic。

Thanks,

Brian Gianforcaro

2 个解决方案

#1


10  

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.

使用composite.setBackgroundMode(SWT.INHERIT_DEFAULT),但不要直接绘制合成 - 使用composite.setBackgroundImage(Image)绘制图像并将其设置为背景图像。除非我错过了一个技巧,否则这意味着你只需要在复合大小时重新生成图像。

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();
        }
    }

}

#2


-1  

The first thing I would try is to capture an image from the widget and paint the portion of the image where the child widget is located onto the child widget directly.

我要尝试的第一件事是从窗口小部件捕获图像,并直接将子窗口小部件所在的图像部分绘制到子窗口小部件上。

If that doesn't work, try using the same paint listener for both widget, but before to set the GC's transform to after transforming the GC to translate coordinates to the label's coordinate space:

如果这不起作用,请尝试对两个窗口小部件使用相同的绘图侦听器,但在将GC的变换设置为转换GC以将坐标转换为标签的坐标空间之前:

Listener listener = new Listener () {
  public void handleEvent (Event e) {
    GC gc = e.gc;
    Rectangle rect = composite.getClientArea ();
    Point offset = ((Control)e.widget).toControl(composite.toDisplay(0, 0));
    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 + offset.x, rect.y + offset.y,
        rect.width, rect.height , true);
  }
}
composite.addListener (SWT.Paint, listener);
label.addListener(SWT.Paint, listener);

Also, be careful to dispose any Color instances you create after you are done with them. Otherwise you will leak system resources and eventually run out.

另外,在完成之后,请小心处理您创建的任何Color实例。否则,您将泄漏系统资源并最终耗尽。

#1


10  

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.

使用composite.setBackgroundMode(SWT.INHERIT_DEFAULT),但不要直接绘制合成 - 使用composite.setBackgroundImage(Image)绘制图像并将其设置为背景图像。除非我错过了一个技巧,否则这意味着你只需要在复合大小时重新生成图像。

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();
        }
    }

}

#2


-1  

The first thing I would try is to capture an image from the widget and paint the portion of the image where the child widget is located onto the child widget directly.

我要尝试的第一件事是从窗口小部件捕获图像,并直接将子窗口小部件所在的图像部分绘制到子窗口小部件上。

If that doesn't work, try using the same paint listener for both widget, but before to set the GC's transform to after transforming the GC to translate coordinates to the label's coordinate space:

如果这不起作用,请尝试对两个窗口小部件使用相同的绘图侦听器,但在将GC的变换设置为转换GC以将坐标转换为标签的坐标空间之前:

Listener listener = new Listener () {
  public void handleEvent (Event e) {
    GC gc = e.gc;
    Rectangle rect = composite.getClientArea ();
    Point offset = ((Control)e.widget).toControl(composite.toDisplay(0, 0));
    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 + offset.x, rect.y + offset.y,
        rect.width, rect.height , true);
  }
}
composite.addListener (SWT.Paint, listener);
label.addListener(SWT.Paint, listener);

Also, be careful to dispose any Color instances you create after you are done with them. Otherwise you will leak system resources and eventually run out.

另外,在完成之后,请小心处理您创建的任何Color实例。否则,您将泄漏系统资源并最终耗尽。