Etiqueta/botón transparente SWT

He investigado esto durante días. Parece que la mayoría de la gente quiere colocar botones en un lienzo o capa transparente. Necesito colocar objetos transparentes en los que se pueda hacer clic sobre un lienzo/componente. En mis pruebas, descubro que si no intento colocar el objeto en el lienzo, simplemente nunca se muestra.

En el proyecto final, la aplicación mostrará objetos animados con una serie de controles para los que planeo usar imágenes.

En el ejemplo que estoy tratando de resolver, tomé Snipped195 que muestra un toroide giratorio. Estoy tratando de colocar una etiqueta de imagen sobre el toro de modo que, a medida que el toro gira, se muestre a través del área de la etiqueta que es transparente. He configurado un archivo gif que es un signo más rojo y tiene un fondo transparente. También recogí un código (no recuerdo de dónde vino ahora) que es parte del método paintControl que busca píxeles transparentes y construye un objeto Región. El objeto región obviamente está haciendo lo que debe hacer para definir a dónde va la imagen. ¿Necesito aplicar la región de alguna manera a la imagen en lugar del lienzo?

Al principio, cuando traté de hacer esto, obtuve la imagen mostrada. Sin embargo, donde las áreas transparentes donde se muestra en blanco. Después de implementar el código paintControl, al menos manejó el área transparente correctamente. Ahora necesito mostrar el contenido de la imagen real.

Construí un objeto para cuidar la etiqueta de la imagen. Lo llamé TransparentImageLabel. Parece que:

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

Después de agregar esto a Snipped195, el código se ve así:

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

tengo que estar cerca Las áreas de la imagen que se definen como transparentes se dibujan como transparentes. Pero no obtengo nada más que un plus blanco en lugar del rojo que está en la imagen.

enter image description here

preguntado el 13 de enero de 13 a las 21:01

¿Podría proporcionar la imagen transparente que está tratando de dibujar en el lienzo ...? -

1 Respuestas

El problema está en tu TransparentImageLabel#paintControl(..) método. Corrija la penúltima línea a lo siguiente:

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

Dado que está dibujando dentro del contexto del lienzo, las coordenadas que especifique para la ubicación deben ser relativas a eso Canvas. Actualmente está utilizando la ubicación de canvas que se devuelve en relación con su padre.

Respondido el 14 de enero de 13 a las 15:01

Eso solucionó el problema. Funciona bien sobre la hélice giratoria. Muchísimas gracias. Dado que se recogió de las sugerencias en los foros, todavía estoy aprendiendo cómo funciona el código. Probé esto con la hélice giratoria. Pero se usará para repasar un mapa en movimiento. El mapa se vuelve a dibujar 25 veces por segundo y el centro se reposiciona usando OpenGL. El botón transparente necesita un evento de redibujado vinculado al mapa para que pueda redibujarse cada vez que se dibuja el mapa. El propósito de canvas.addPaintListener es señalar que se vuelve a dibujar el botón cada vez que se vuelve a dibujar la hélice. ¿Es eso correcto? - user1974846

Ha pasado un tiempo que leí este código, así que no estoy exactamente seguro. Pero puedes probarlo. Dado que la imagen que está agregando es un control separado (un elemento secundario de GLCanvas), es posible que no necesite volver a dibujar cada vez que se dibuja el elemento principal. Pruébalo y házmelo saber también. Y es posible que desee aceptar la respuesta si resolvió el problema. - Waqas Ilias

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.