SWT透明按钮/标签

时间:2013-01-13 21:36:54

标签: java swt

我已经研究了好几天了。似乎大多数人都希望将按钮放在透明的画布或外壳上。我需要在画布/组件上放置透明的可点击对象。在我的测试中,我发现如果我不尝试将对象放在画布上,它就永远不会显示。

在最终项目中,应用程序将显示动画对象,其中包含我计划使用图像的多个控件。

在我试图解决的例子中,我采用了Snipped195,它显示了一个转动的圆环。我试图在圆环上放置一个图像标签,这样当圆环转动时,它将通过标签的透明区域显示出来。我已经设置了一个红色加号的gif文件,并且背景透明。我还挑选了一些代码(不记得它从哪里来),它是paintControl方法的一部分,它查找透明像素并构建Region对象。区域对象显然正在做它需要做的事情来定义图像的去向。我是否需要以某种方式将区域应用于图像而不是画布?

首先,当我尝试这样做时,我确实显示了图像。但是它显示白色的透明区域。在实现paintControl代码之后,它至少正确地处理了透明区域。现在我需要显示实际的图像内容。

我构建了一个对象来处理图像标签。我称之为TransparentImageLabel。它看起来像:

public class TransparentImageLabel extends Canvas {

    private Image labelImage;

    public TransparentImageLabel(Composite parent, Image image, int style) {
        super(parent, style);
        this.labelImage = image;
        addDisposeListener(new DisposeListener() {
            public void widgetDisposed(DisposeEvent e) {
                TransparentImageLabel.this.widgetDisposed(e);
            }
        });
        addPaintListener(new PaintListener() {
            public void paintControl(PaintEvent e) {
                TransparentImageLabel.this.paintControl(e);
            }
        });
    }

    private void widgetDisposed(DisposeEvent e) {

    }

    private void paintControl(PaintEvent event) {
        System.out.println("at paint control");
        ImageData imgData = this.labelImage.getImageData();
        Region region = new Region();
        if (imgData.alphaData != null) {
            Rectangle pixel = new Rectangle(0, 0, 1, 1);
            for (int y = 0; y < imgData.height; y++) {
                for (int x = 0; x < imgData.width; x++) {
                    if (imgData.getAlpha(x, y) == 255) {
                        pixel.x = imgData.x + x;
                        pixel.y = imgData.y + y;
                        region.add(pixel);
                    }
                }
            }
        } else {
            ImageData mask = imgData.getTransparencyMask();
            Rectangle pixel = new Rectangle(0, 0, 1, 1);
            for (int y = 0; y < mask.height; y++) {
                for (int x = 0; x < mask.width; x++) {
                    if (mask.getPixel(x, y) != 0) {
                        pixel.x = imgData.x + x;
                        pixel.y = imgData.y + y;
                        region.add(pixel);
                    }
                }
            }
        }
        this.setRegion(region);
        event.gc.drawImage(labelImage, this.getBounds().x, this.getBounds().y);
        region.dispose();
    }
}

将此内容添加到Snipped195后,代码如下:

public class Snippet195 {

    private Image redPlus;

    static void drawTorus(float r, float R, int nsides, int rings) {
        float ringDelta = 2.0f * (float) Math.PI / rings;
        float sideDelta = 2.0f * (float) Math.PI / nsides;
        float theta = 0.0f, cosTheta = 1.0f, sinTheta = 0.0f;
        for (int i = rings - 1; i >= 0; i--) {
            float theta1 = theta + ringDelta;
            float cosTheta1 = (float) Math.cos(theta1);
            float sinTheta1 = (float) Math.sin(theta1);
            GL11.glBegin(GL11.GL_QUAD_STRIP);
            float phi = 0.0f;
            for (int j = nsides; j >= 0; j--) {
                phi += sideDelta;
                float cosPhi = (float) Math.cos(phi);
                float sinPhi = (float) Math.sin(phi);
                float dist = R + r * cosPhi;
                GL11.glNormal3f(cosTheta1 * cosPhi, -sinTheta1 * cosPhi, sinPhi);
                GL11.glVertex3f(cosTheta1 * dist, -sinTheta1 * dist, r * sinPhi);
                GL11.glNormal3f(cosTheta * cosPhi, -sinTheta * cosPhi, sinPhi);
                GL11.glVertex3f(cosTheta * dist, -sinTheta * dist, r * sinPhi);
            }
            GL11.glEnd();
            theta = theta1;
            cosTheta = cosTheta1;
            sinTheta = sinTheta1;
        }
    }

    private Snippet195() {
        final Display display = new Display();
        Shell shell = new Shell(display, SWT.NO_REDRAW_RESIZE);
        shell.setLayout(new FillLayout());
        Composite comp = new Composite(shell, SWT.NONE);
        comp.setLayout(new FillLayout());
        GLData data = new GLData();
        data.doubleBuffer = true;
        redPlus = new Image(shell.getDisplay(), new ImageData(
                Snippet237.class.getResourceAsStream("/red-plus.png")));
        final GLCanvas canvas = new GLCanvas(comp, SWT.NONE, data);

        canvas.addPaintListener(new PaintListener() {
            public void paintControl(PaintEvent e) {
                e.gc.setAlpha(15);
                e.gc.drawImage(Snippet195.this.redPlus, 0, 0);
            }
        });

        canvas.setCurrent();
        try {
            GLContext.useContext(canvas);
        } catch (LWJGLException e) {
            e.printStackTrace();
        }

        canvas.addListener(SWT.Resize, new Listener() {
            public void handleEvent(Event event) {
                Rectangle bounds = canvas.getBounds();
                float fAspect = (float) bounds.width / (float) bounds.height;
                canvas.setCurrent();
                try {
                    GLContext.useContext(canvas);
                } catch (LWJGLException e) {
                    e.printStackTrace();
                }
                GL11.glViewport(0, 0, bounds.width, bounds.height);
                GL11.glMatrixMode(GL11.GL_PROJECTION);
                GL11.glLoadIdentity();
                GLU.gluPerspective(45.0f, fAspect, 0.5f, 400.0f);
                GL11.glMatrixMode(GL11.GL_MODELVIEW);
                GL11.glLoadIdentity();
            }
        });

        GL11.glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
        GL11.glColor3f(1.0f, 0.0f, 0.0f);
        GL11.glHint(GL11.GL_PERSPECTIVE_CORRECTION_HINT, GL11.GL_NICEST);
        GL11.glClearDepth(1.0);
        GL11.glLineWidth(2);
        GL11.glEnable(GL11.GL_DEPTH_TEST);
        TransparentImageLabel redPlusLabel = new TransparentImageLabel(canvas,
                redPlus, SWT.NONE);
        redPlusLabel.setSize(48, 48);
        redPlusLabel.setLocation(500, 200);
        shell.setText("SWT/LWJGL Example");
        shell.setSize(880, 720);
        shell.open();
        final Runnable run = new Runnable() {
            int rot = 0;

            public void run() {
                if (!canvas.isDisposed()) {
                    canvas.setCurrent();
                    try {
                        GLContext.useContext(canvas);
                    } catch (LWJGLException e) {
                        e.printStackTrace();
                    }
                    GL11.glClear(GL11.GL_COLOR_BUFFER_BIT
                            | GL11.GL_DEPTH_BUFFER_BIT);
                    GL11.glClearColor(.3f, .5f, .8f, 1.0f);
                    GL11.glLoadIdentity();
                    GL11.glTranslatef(0.0f, 0.0f, -10.0f);
                    float frot = rot;
                    GL11.glRotatef(0.15f * rot, 2.0f * frot, 10.0f * frot, 1.0f);
                    GL11.glRotatef(0.3f * rot, 3.0f * frot, 1.0f * frot, 1.0f);
                    rot++;
                    GL11.glPolygonMode(GL11.GL_FRONT_AND_BACK, GL11.GL_LINE);
                    GL11.glColor3f(0.9f, 0.9f, 0.9f);
                    drawTorus(1, 1.9f + ((float) Math.sin((0.004f * frot))), 25, 75);
                    canvas.swapBuffers();
                    display.asyncExec(this);
                }
            }
        };
        canvas.addListener(SWT.Paint, new Listener() {
            public void handleEvent(Event event) {
                run.run();
            }
        });
        display.asyncExec(run);

        while (!shell.isDisposed()) {
            if (!display.readAndDispatch())
                display.sleep();
        }
        display.dispose();
    }

    public static void main(String[] args) {
        new Snippet195();
    }
}

我必须要亲近。定义为透明的图像区域被绘制为透明。但是我没有得到任何东西,只有白色加上而不是图像中的红色。

enter image description here

1 个答案:

答案 0 :(得分:2)

问题出在您的TransparentImageLabel#paintControl(..)方法中。将第二行最后一行更正为:

event.gc.drawImage(labelImage, 0, 0);

由于您是在画布的上下文中绘制的,因此您为位置指定的坐标应该相对于Canvas。您当前正在使用相对于其父级返回的canvas位置。