2013-01-13 120 views
4

我已經研究了幾天。看來大多數人想要將按鈕放在透明的畫布或外殼上。我需要在畫布/組件上放置透明的可點擊對象。在我的測試中,我發現如果我不試圖將對象放在畫布上,它就不會顯示。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

+0

你可以提供你正試圖繪製到畫布的透明圖像..? – Sorceror

回答

2

的問題是在你的TransparentImageLabel#paintControl(..)方法。更正倒數第二行到以下幾點:

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

因爲你是在畫布的範圍內繪圖,所以你指定的位置座標應該是相對於該Canvas。您目前正在使用相對於其父母返回的canvas的位置。

+0

解決了這個問題。它在旋轉螺旋上工作良好。非常感謝你。由於它是從論壇上的建議,我仍然在學習代碼如何工作。我用旋轉螺旋測試了這個。但它會被用來瀏覽移動的地圖。地圖重繪每秒25次,中心使用OpenGL重新定位。透明按鈕需要一個與地圖綁定的重繪事件,以便每次繪製地圖時都可以重繪。 canvas.addPaintListener的用途是在每次螺旋線重繪時發出按鈕重繪的信號。那是對的嗎? – user1974846

+0

它已經有一段時間了,我讀了這段代碼,所以我不太確定。但你可以試試看。由於您要添加的圖像是一個單獨的控件(GLCanvas的子控件),因此每次繪製父圖時都可能不需要重繪。試一下,讓我知道。如果它解決了問題,你可能想接受答案。 –