如何在SWT中实现标签继承复合组件的GC

8

我正在编写一个应用程序,我们的设计师想在一些组合中使用渐变背景。

我编写了以下代码:

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

        }
    });

这在合成图像上正确绘制了渐变,但是我们在合成图像上覆盖了标签/带标签的控件、画布和链接。
在这些区域中,背景只是绘制空画布时得到的纯灰色。
我尝试强制让标签继承背景,如下所示:
label.setBackgroundMode(SWT.INHERIT_DEFAULT) //SWT.INHERIT_FORCE Doesn't work either

但是这样会让我只有相同的默认灰色,并且没有渐变背景放在组合的顶部组件后面。
有没有什么建议可以使每个元素的背景都成为渐变?
我不反对使用提供图像并将渐变绘制到gc上,然后将背景设置为该图像的方法。但是,该方法根本没有起作用,无论是复合框还是其任何元素。
此外,据我所知,无法单独设置渐变。我们希望整个复合框都是一个统一的流动渐变。
[编辑] 我上传了一个示例到twitpic here
谢谢,
Brian Gianforcaro
2个回答

10

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

你应该能够直接复制粘贴此代码以查看我的意思:

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

}

稍加修改和调整后,这个工作得非常好。谢谢! - Brian Gianforcaro
没有必要设置背景图片。对我来说,设置颜色也可以很好地工作。 - Mot

-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:

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.


这是一个好主意,但它依赖于控件实际的图形处理(gc),所以控件上的任何文本或内容都将被覆盖。 - Brian Gianforcaro

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接