2013-01-13 5 views
4

나는 이것을 수 일간 연구했다. 대부분의 사람들은 투명 캔버스 나 셸에 버튼을 배치하려고합니다. 캔버스/컴포넌트 위에 투명한 클릭 가능한 객체를 배치해야합니다. 내 테스트에서 캔버스에 객체를 놓으려고 시도하지 않으면 단순히 표시되지 않는다는 것을 알게되었습니다.SWT 투명 버튼/라벨

최종 프로젝트에서 이미지를 사용할 계획의 컨트롤이있는 애니메이션 개체가 응용 프로그램에 표시됩니다.

예제에서 나는 회전 토러스를 표시하는 Snipped195를 가져 왔습니다. 토러스가 바뀌면 레이블의 투명 영역을 통해 표시되도록 토러스 위에 이미지 레이블을 배치하려고합니다. 빨간색 더하기 기호이며 투명 배경을 가진 gif 파일을 설정했습니다. 또한 투명 픽셀을 찾고 Region 객체를 빌드하는 paintControl 메서드의 일부인 코드를 포착했습니다 (현재는 어디에서 왔는지 기억할 수 없습니다). region 객체는 분명히 이미지가 어디로 가야하는지 정의하기 위해 필요한 것을 수행하고 있습니다. 캔버스가 아닌 이미지에 어떻게 든 영역을 적용해야합니까?

처음에는이 작업을 시도 할 때 이미지가 표시되었습니다. 그러나 어디에 흰색이 표시되는 투명 영역. paintControl 코드를 구현 한 후 적어도 투명 영역을 올바르게 처리했습니다. 이제 실제 이미지 콘텐츠를 표시해야합니다.

나는 이미지 라벨을 관리하기 위해 객체를 만들었습니다. 나는 그것을 TransparentImageLabel이라고 불렀다. 내가 가까이해야

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

: 같은

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이를 추가 한 후 코드가 같습니다 것 같습니다. 투명하게 정의 된 이미지 영역은 투명하게 그려집니다. 그러나 나는 이미지에있는 빨간색 대신에 흰색 플러스를 얻지 못하고 있습니다.

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의 자식)이므로 부모가 그려 질 때마다 다시 그리기가 필요하지 않을 수도 있습니다. 그것을 밖으로 시도하고 나도 알려주세요. 그리고 문제가 해결되면 대답을 받아 들일 수도 있습니다. –