2017-10-09 1 views
1

SWT를 사용하여 사용자 지정 슬라이더를 만들려고하는데 이상한 결과가 발생했습니다. 여기에 뭔가가 누락되었으므로 여백이있는 내부 캔버스가있는 컴포지트를 갖고 싶습니다. 모든 주위 15 위, 왼쪽 및 오른쪽 하단. 이와 유사한 뭔가 : 레이아웃 및 마우스 이벤트

enter image description here

그래서 내가 쓴이 같은 주 :

Main.java

import org.eclipse.swt.SWT; 
import org.eclipse.swt.layout.GridLayout; 
import org.eclipse.swt.widgets.Display; 
import org.eclipse.swt.widgets.Shell; 
import org.eclipse.swt.widgets.Text; 

public class Main { 

public static void main (String [] args) { 
    Display display = new Display(); 
    Shell shell = new Shell(display); 
    shell.setLayout(new GridLayout(1,false)); 
    shell.setSize(400,400); 
    CustomSlider slider= new CustomSlider(shell, SWT.NONE); 


    shell.pack(); 
    shell.open(); 

    while (!shell.isDisposed()) { 
     if (!display.readAndDispatch()) display.sleep(); 
    } 
    display.dispose(); 
} 
} 

그리고 복합 확장 customSlider 클래스 :

import org.eclipse.swt.SWT; 
import org.eclipse.swt.events.PaintEvent; 
import org.eclipse.swt.events.PaintListener; 
import org.eclipse.swt.graphics.GC; 
import org.eclipse.swt.graphics.Point; 
import org.eclipse.swt.graphics.Rectangle; 
import org.eclipse.swt.layout.GridData; 
import org.eclipse.swt.layout.GridLayout; 
import org.eclipse.swt.widgets.Canvas; 
import org.eclipse.swt.widgets.Composite; 
import org.eclipse.swt.widgets.Display; 
import org.eclipse.swt.widgets.Event; 
import org.eclipse.swt.widgets.Listener; 
import org.eclipse.swt.widgets.Widget; 

public class CustomSlider extends Composite { 
    private Canvas progressBar; 
    private Rectangle progressBarRect; 
    private int knobSize=15; 
    private Point thisSize; 
    private boolean hover=false; 
    public CustomSlider(Composite arg0, int arg1) { 
     super(arg0, arg1); 
     thisSize= new Point(400, 50); 
     setSize(400, 50); 
     setBackground(arg0.getDisplay().getSystemColor(SWT.COLOR_MAGENTA)); 
     GridLayout gl= new GridLayout(1,false); 
     setLayout(gl); 
     setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); 


     progressBar = new Canvas(this, SWT.NONE); 
     GridLayout gl2= new GridLayout(1,false); 
     gl2.marginBottom=knobSize; 
     gl2.marginTop=knobSize; 
     gl2.marginLeft=knobSize; 
     gl2.marginRight=knobSize; 
     gl2.marginWidth=knobSize; 
     gl2.marginHeight=knobSize; 
     progressBar.setLayout(gl2); 
     GridData gd=new GridData(SWT.FILL, SWT.FILL, true, true); 

     progressBar.setLayoutData(gd); 
     progressBar.addPaintListener(new PaintListener() { 

      @Override 
      public void paintControl(PaintEvent arg0) { 
       Canvas canvasProgress=(Canvas)arg0.widget; 
       progressBarRect= canvasProgress.getBounds(); 

       GC gc=arg0.gc; 
       gc.setForeground(canvasProgress.getDisplay().getSystemColor(SWT.COLOR_GREEN)); 
       if (hover){ 
       gc.setBackground(canvasProgress.getDisplay().getSystemColor(SWT.COLOR_RED)); 
       }else{ 
        gc.setBackground(canvasProgress.getDisplay().getSystemColor(SWT.COLOR_BLUE)); 
       } 
       gc.fillRectangle(progressBarRect); 
       gc.drawRectangle(progressBarRect); 

      } 
     }); 


     Listener listener = new Listener() { 
       public void handleEvent(Event event) { 
        System.out.println("---------------"); 
        System.out.println("Canvas:"+((Canvas)event.widget).getBounds()); 
        System.out.println("Composite:"+((Canvas)event.widget).getParent().getBounds()); 
        System.out.println("Shell:"+((Canvas)event.widget).getParent().getParent().getBounds()); 
        Display display=((Widget)event.widget).getDisplay(); 
       switch (event.type) { 

       case SWT.MouseHover: 
        if (progressBarRect.contains(new Point(event.x, event.y))){ 

          hover=true; 
         }else{ 

          hover=false; 
         } 
         break; 

       case SWT.MouseDown: 

        break; 
       case SWT.MouseMove: 
        if (progressBarRect.contains(new Point(event.x, event.y))){ 

          hover=true; 
         }else{ 

          hover=false; 
         } 

        break; 
       case SWT.MouseEnter: 
        if (progressBarRect.contains(new Point(event.x, event.y))){ 

          hover=true; 
         }else{ 

          hover=false; 
         } 

        break; 
       case SWT.MouseExit: 
        if (progressBarRect.contains(new Point(event.x, event.y))){ 
         System.out.println("progressBarRect:"+progressBarRect); 
         System.out.println("Point"+new Point(event.x, event.y)); 
         System.out.println("HOVER!"); 
          hover=true; 
         }else{ 
          System.out.println("OUT!"); 
          hover=false; 
         } 

        break; 
       case SWT.MouseUp: 

        break; 


       } 
       display.asyncExec(() -> progressBar.redraw()); 
       } 
      }; 
      progressBar.addListener(SWT.MouseDown, listener); 
      progressBar.addListener(SWT.MouseUp, listener); 
      progressBar.addListener(SWT.MouseMove, listener); 
      progressBar.addListener(SWT.MouseExit, listener); 
      progressBar.addListener(SWT.MouseEnter, listener); 
      progressBar.addListener(SWT.MouseHover, listener); 



    } 
    public Point getThisSize() { 
     return thisSize; 
    } 
    public void setThisSize(Point thisSize) { 
     this.thisSize = thisSize; 
    } 


} 

이제 가장 먼저하는 것은 해상도입니다. ULT는 단지 두 개의 (왼쪽 상단) 마진이 고려되지 않은 것, 또는 더 나은, 내가 원하는 것을 일치하지 않습니다

enter image description here

둘째, 사건은 예상치 못한 결과에 결과 : MouseExit 이벤트 비록 내가 복합체에서 벗어난다 할지라도 나는 캔버스를 맴돌고 있다고 말한다. : S

enter image description here

당신은 내가 여기에 무슨 일이 일어나고 있는지 이해하는 데 도움시겠습니까? CustomSlider2을

import org.eclipse.swt.SWT; 
import org.eclipse.swt.layout.GridLayout; 
import org.eclipse.swt.widgets.Display; 
import org.eclipse.swt.widgets.Shell; 


public class Main { 

public static void main (String [] args) { 
    Display display = new Display(); 
    Shell shell = new Shell(display); 
    shell.setLayout(new GridLayout(1,false)); 
    //shell.setSize(400,400); 
    CustomSlider2 slider= new CustomSlider2(shell, SWT.NONE); 


    shell.pack(); 
    shell.open(); 

    while (!shell.isDisposed()) { 
     if (!display.readAndDispatch()) display.sleep(); 
    } 
    display.dispose(); 
} 
} 

및 사용자 정의 슬라이더가 될 :

홈페이지 :

편집

나는 다음과 같은 내 코드를 편집 그렉의 제안에 따라 ... 미리 감사

import org.eclipse.swt.SWT; 
import org.eclipse.swt.events.PaintEvent; 
import org.eclipse.swt.events.PaintListener; 
import org.eclipse.swt.graphics.GC; 
import org.eclipse.swt.graphics.Rectangle; 
import org.eclipse.swt.layout.GridData; 
import org.eclipse.swt.layout.GridLayout; 
import org.eclipse.swt.widgets.Canvas; 
import org.eclipse.swt.widgets.Composite; 
import org.eclipse.swt.widgets.Display; 
import org.eclipse.swt.widgets.Event; 
import org.eclipse.swt.widgets.Listener; 
import org.eclipse.swt.widgets.Widget; 

public class CustomSlider2 extends Composite { 
    private Canvas progressBar; 
    private Rectangle progressBarRect; 
    private int knobSize=15; 

    private boolean hover=false; 
    public CustomSlider2(Composite arg0, int arg1) { 
     super(arg0, arg1); 
     setBackground(arg0.getDisplay().getSystemColor(SWT.COLOR_MAGENTA)); 
     setLayout(new GridLayout(1,false)); 

     progressBar = new Canvas(this, SWT.CENTER); 
     final GridData gd=new GridData(SWT.FILL, SWT.FILL, true, true); 
     gd.widthHint = 100; 
     gd.heightHint = 50; 
     GridLayout gl= new GridLayout(); 
     gl.numColumns=1; 
     gl.marginWidth=knobSize; 
     gl.marginHeight=knobSize; 
     progressBar.setLayoutData(gd); 
     progressBar.setLayout(gl); 



     progressBar.addPaintListener(new PaintListener() { 

      @Override 
      public void paintControl(PaintEvent arg0) { 
       Canvas canvasProgress=(Canvas)arg0.widget; 
       Rectangle clientArea= canvasProgress.getBounds(); 
       progressBarRect=new Rectangle(clientArea.x, clientArea.y, clientArea.x + clientArea.width - 1, clientArea.y + clientArea.height - 1); 
       GC gc=arg0.gc; 
       gc.setForeground(canvasProgress.getDisplay().getSystemColor(SWT.COLOR_GREEN)); 
       if (hover){ 
        gc.setBackground(canvasProgress.getDisplay().getSystemColor(SWT.COLOR_RED)); 
       }else{ 
        gc.setBackground(canvasProgress.getDisplay().getSystemColor(SWT.COLOR_BLUE)); 
       } 
       gc.fillRectangle(progressBarRect); 
       gc.drawRectangle(progressBarRect); 

      } 
     }); 


     Listener listener = new Listener() { 
      public void handleEvent(Event event) { 
       System.out.println("---------------"); 
       System.out.println("Canvas:"+((Canvas)event.widget).getBounds()); 
       System.out.println("Composite:"+((Canvas)event.widget).getParent().getBounds()); 
       System.out.println("Shell:"+((Canvas)event.widget).getParent().getParent().getBounds()); 
       Display display=((Widget)event.widget).getDisplay(); 
       switch (event.type) { 
       case SWT.MouseEnter: 
        hover=true; 
        break; 
       case SWT.MouseExit: 
        hover=false;  
        break; 


       } 
       display.asyncExec(() -> progressBar.redraw()); 
      } 
     }; 

     progressBar.addListener(SWT.MouseExit, listener); 
     progressBar.addListener(SWT.MouseEnter, listener); 


    } 


} 

이벤트 문제가 해결되었지만 레이아웃 하나가 아닌 것 같습니다. 캔버스 주위에 여백이 없습니다. ...

+0

'setSize' (또는'setBounds')와 레이아웃을 섞지 마십시오. 레이아웃이 크기보다 우선합니다. –

+0

안녕하세요 그렉,하지만 난 그것을 섞어하지 않았다, 내가 사용하는 설정 크기를 합성 (CustomSlider)하고 SWT 캔버스의 경계를 결정하자하지만 SWT는 주위에 여백을 가지고 캔버스 n 순서에 대한 그리드 레이아웃을 사용하도록 ... 그게 뭐가 잘못 됐니? – navy1978

+0

Composite에서 setSize를 주석 처리하여 결과가 변경되지 않고 여백이 위쪽과 왼쪽에만 적용됩니다 ... ( – navy1978

답변

1

레이아웃을 사용할 때 레이아웃 너비와 높이 힌트를 사용하여 컨트롤의 크기 제안. 그래서 여기 당신은 사용할 수 있습니다 :

final GridData gd=new GridData(SWT.FILL, SWT.FILL, true, true); 
gd.widthHint = 400; 
gd.heightHint = 50; 
progressBar.setLayoutData(gd); 

을 당신에게 레이아웃 추가 국경을 포함하여 컨트롤의 전체 크기를 제공 getBounds을 사용하는 paintControl에서. 그러나 fillRectangle과 같은 조작은 항상 경계를 제외하는 '클라이언트 영역'을 그립니다. 따라서 페인트는 다음과 같아야합니다.

@Override 
public void paintControl(PaintEvent event) { 
    Canvas canvasProgress = (Canvas)event.widget; 
    Rectangle clientArea = canvasProgress.getClientArea(); // Client area 

    .. set colors 

    gc.fillRectangle(clientArea.x, clientArea.y, clientArea.x + clientArea.width - 1, clientArea.y + clientArea.height - 1); 
    gc.drawRectangle(clientArea.x, clientArea.y, clientArea.x + clientArea.width - 1, clientArea.y + clientArea.height - 1); 
} 

마우스 움직임의 경우 이벤트의 위치를 ​​확인할 필요가 없습니다. MouseExit는 마우스가 컨트롤을 벗어날 때만 호출됩니다.

+0

안녕하세요 그렉, 이벤트 관련 문제는 수정되었지만 레이아웃이 아닌 것 같습니다 ... 아직 캔버스 주변에 여백이 없습니다 ... 내 질문에 편집했습니다. w code ...) – navy1978

+1

당신은 여전히'paintControl'에서'getBounds'를 사용하고 있습니다, 이것은'getClientArea' 여야합니다. –

+0

내 실수! 당신 말이 맞아요! – navy1978