2017-10-09 214 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

能否請你幫我明白這到底是怎麼回事呢?

預先感謝您...

編輯 繼格雷格的建議修改我的代碼如下:

主營:

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

和自定義滑塊成爲CustomSlider2:

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使用畫布的網格佈局,以便邊緣四周...那有什麼問題? – navy1978

+0

我已經做了一個測試,甚至註釋了複合材料上的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

您好格雷格,事件的問題似乎是固定的,但沒有佈局的問題......我仍然沒有畫布邊緣......(我已經用ne編輯了我的問題w代碼...) – navy1978

+1

您仍然在'paintControl'中使用'getBounds',它必須是'getClientArea'。 –

+0

我的錯誤!你是對的! – navy1978