SWT技术总结【显示效果篇】

从前一直从事Web开发,研究了很多JsCSS做出来的效果,不过随着Flash越来越流行跟强大,似乎在现实特效上将来还是Flash的天下,但数据处理上不知道ActionScript是否能够取代Js呢?不过需求只是简约风格的网站的话,JsCSS就足够了。最近一直在用SWT做东西,虽然桌面系统不需要做得太花哨,但该有的效果和用户体验是必须的,所以就总结了一下桌面开发中如何用SWT实现Web界面类似的效果。

 

(一)首先SWT的独立窗口是以Shell对象来显示的,每个Application必须有一个最顶层的Shell,所有的窗口图片等资源都依托于顶层的Display,如果要做一个弹出窗口,就需要创建一个子Shell,可以是模态和非模态的,举个例子:

 

创建一个子窗口,继承Shell写一个自己的窗口类:

public PropUp extends Shell implements MouseMoveListenr, MouseListener{
    private Shell parent;
    private Composite northPan;
    private Point location;
 
    public PropUp(){
    super(parent,SWT.NO_TRIM);
   
    northPan = new Composite(this,SWT.NONE);
    northPan.addMouseMoveListener(this);
    northPan.addMouseListener(this);
}
 
@Override
    protected void checkSubclass() {
        //ignore method
    }
 
    //省略
}

原理说明:

自己继承Shell实现自己的Shell类必须要重写父类的checkSubclass方法,否则自定义Shell无法open显示。一般我们想构造自己的Shell都希望有自己的图片做背景风格,但因为SWT底层调用操作系统的API来完成任务所以就会带上操作系统的ToolBar,上面会有最小化、最大化和关闭这几个按键,而且整个ToolBar的颜色和样式都跟操作系统主题一致,无法改变。如果希望ToolBarShell自身的Background Image一样可以使用自己的图片就把Shell定义为SWT.NO_TRIM类型,表示不需要自带ToolBar,那么所谓的ToolBar就要自己来实现,做为整体Shell的一个内部Panel来实现,PanelSWT里以Composite来实现。自定义一个northPan,应用喜欢的ToolBar图片。不过去掉默认的ToolBar之后窗口就无法随鼠标点击拖动变换位置了,这个效果也需要我们自己做了:

 

要做到鼠标点击拖动就需要一个MouseMoveListener和一个MouseListener,这里我使用自定义Shell实现了这两个接口。我定义了一个location来记录鼠标移动的坐标,给northPan加上这两个监听器,MouseListenermouseDown时记录鼠标按下我们ToolBar的坐标,MouseMoveListenermouseMove不断更新这个location,最后在MouseListenermouseUp方法上得到最终的location坐标,再调用ShellsetLocation把窗口移动过去,就完成了这个效果。

 

(二)另外我们的按钮需要使用图片的话,肯定不希望按钮的图片只有一种状态,就像Web开发中控件的mouseOvermouseOut事件一样,对SWTButton也可以添加这两个效果。举例说明:

 

Button btn = new Button(shell,SWT.NONE);
btn.setImage(plainImage);
btn.addMouseTrackListener(listener);
btn.addMouseListener(listener);


原理说明:

这里首先构造一个按钮对象,给定类型为SWT.NONE表示不需要默认的任何效果(边框之类的)。然后借助几个监听器,在MouseTrackListenermouseEnter方法中将btnImage设置成自己制作的overImage图片,在mouseExit方法中重新设置回到plainImage;在MouseListenermouseDown方法中将btnImage设置成自己制作的downImage,在mouseUp方法中重新设置回到plainImage。这样就完成了对一个按钮的样式修饰。如果有需要的话,Label对象一样可以做这个效果,不过Label对象不响应点击事件,即无法对Label添加SelectionListener对象,所以如果要符合一般用户体验尝试,需要可点击的Label的话,建议用Link对象来取代LabelLink对象就带有addSelectionListener方法。

 

(三)SWT底层调用操作系统的API来完成控件描绘,有时碰到透明图片,我们希望能够像在浏览器中一样透明部分不显示出来,比如整个窗口是一个很明显的圆角甚至椭圆、三角。美工做出来的实际图片当然肯定是矩形,只是那些透明部分无法在桌面真正的透明,这个效果也需要我们自己去做。

 

public class MyWindow extends Shell implements ControlListener{
 
//省略
 
@Override
public void controlResized(ControlEvent e) {
        int w = getSize().x;
        int h = getSize().y;
 
    Region newRegion = new Region();
    newRegion.add(0, 0, getSize().x, getSize().y);
    newRegion.subtract(transparenceRegion (myImage, 0,
            getSize().y - myImage.getBounds().height));
    setRegion(newRegion);
}
 
private Region transparenceRegion(Image image, int offsetX,int offsetY) {
    Region region = new Region();
 
    final ImageData imageData = image.getImageData();
    if (imageData.alphaData != null) {
        Rectangle pixel = new Rectangle(0, 0, 1, 1);
        for (int y = 0; y < imageData.height; y++) {
            for (int x = 0; x < imageData.width; x++) {
                if (imageData.getAlpha(x, y) != 255) {
                    pixel.x = imageData.x + x + offsetX;
                    pixel.y = imageData.y + y + offsetY;
                    region.add(pixel);
                }
            }
        }
    }
    return region;
}
 
@Override
public void controlMoved(ControlEvent e) {
    //ignore method
}


原理说明:

我们通过ControlListener监听器来完成这个效果,忽略controlMoved方法,controlResized中会对窗口的每一次resize动作产生响应,当然初始化第一次显示也算做一次resize动作。在resize发生的时候我们要做的就是把不规则的区域给重新绘制,局部解析图片的透明程度,transparenceRegion方法的offsetXoffsetY两个参数分别代表扫描图片的xy轴起始位置,从这个坐标开始横纵双向的1像素1像素扫描到图片的边界为止,getAlpha方法来读取透明度,它可以识别pnggif中的透明度,如果发现是透明的,就用自制的透明像素各自pixel来取代这一点,这样扫描完之后调用setRegion(newRegion);来填充新绘制的区域,就能在桌面上实现真正的不规则背景的图形控件或者窗口。



 

你可能感兴趣的:(shell,web开发,image,button,actionscript,SWT)