布局和鼠标事件

时间:2017-10-09 07:28:03

标签: java events layout swt

我正在尝试使用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 ();
}
}

扩展Composite的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;
    }


}

现在,首先是结果与我想要的不匹配,似乎边缘没有考虑,或者更好只有两个(顶部和左边):

enter image description here

其次,事件导致意外结果:MouseExit事件说我仍然悬停在画布上,即使我已经离开了复合体! :S

enter image description here

你能帮我理解这里发生了什么吗?

提前谢谢你......

修改 按照Greg的建议,我编辑我的代码如下:

主:

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


    }


}

所以事件问题似乎是固定的,但不是布局问题...我仍然没有画布周围的边距......

1 个答案:

答案 0 :(得分:1)

使用布局时,您可以使用布局宽度和高度提示来设置控件的建议大小。所以你可以在这里使用:

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

在您使用paintControl的{​​{1}}中,它会为您提供控件的完整大小,包括布局添加的边框。但是getBounds之类的操作总是在客户区域中绘制'不包括边界。所以你的油漆应该是这样的:

fillRectangle

对于鼠标移动,无需检查事件中的位置。 MouseExit仅在鼠标离开您的控件时被调用。