I researched this for several days. Most people seem to want to place buttons on a transparent canvas or shell. I need to place transparent objects with a click over the canvas / component. In my testing, I found that if I am not trying to put an object on the canvas, it simply does not appear.
In the final project, the application will display animated objects with several controls that I plan to use for images.
In the example I'm trying to solve, I took Snipped195, which displays a rotary torus. I am trying to put an image label on top of the torus in such a way that as the torus rotates, it will be displayed through the transparent label area. I installed a gif file that is a red plus sign and has a transparent background. I also took the code (I canβt remember where it came from), which is part of the paintControl method, which searches for transparent pixels and creates a Region object. Obviously, the area object does what it needs to determine where the image is going. Do I need to somehow apply a region to an image instead of a canvas?
At first, when I tried to do this, I got an image. However, there are transparent areas where it is displayed in white. After injecting the paintControl code, he at least correctly handled the transparent area. Now I need to display the actual content of the image.
I built an object to take care of the image label. I called it TransparentImageLabel. It looks like this:
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(); } }
After adding to Snipped195, the code is as follows:
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(); } }
I have to be there. Areas of the image that are defined as transparent become transparent. But I get nothing but a white plus instead of the red that is in the image.
