4

私はこれを何日も研究してきました。ほとんどの人は、透明なキャンバスまたはシェルにボタンを配置したいと考えているようです. キャンバス/コンポーネント上に透明なクリック可能なオブジェクトを配置する必要があります。私のテストでは、オブジェクトをキャンバスに配置しようとしないと、オブジェクトがまったく表示されないことがわかりました。

最終的なプロジェクトでは、アプリケーションは、画像を使用する予定の多数のコントロールを備えたアニメーション オブジェクトを表示します。

私が解決しようとしている例では、回転するトーラスを表示する Snipped195 を使用しました。トーラスが回転すると透明なラベルの領域を通して表示されるように、トーラスの上に画像ラベルを配置しようとしています。赤いプラス記号で背景が透明な gif ファイルを設定しました。また、透明なピクセルを探して Region オブジェクトを構築する paintControl メソッドの一部であるコード (今はどこから来たのか思い出せません) も拾いました。領域オブジェクトは、明らかに、画像の移動先を定義するために必要なことを行っています。キャンバスではなく画像に何らかの方法で領域を適用する必要がありますか?

最初にこれをやろうとしたとき、画像が表示されました。ただし、透明な部分が白く表示されます。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();
    }
}

私は近くにいる必要があります。透明として定義されている画像の領域は、透明として描画されています。しかし、画像にある赤ではなく、白のプラスしか得られません。

ここに画像の説明を入力

4

1 に答える 1

2

問題はあなたのTransparentImageLabel#paintControl(..)方法にあります。最後から 2 行目を次のように修正します。

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

キャンバスのコンテキスト内で描画しているため、場所に指定する座標はそれを基準にする必要がありますCanvascanvas現在、その親に対して返される場所を使用しています。

于 2013-01-14T15:40:18.813 に答える