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

来源:互联网 发布:星际争霸1兵种数据 编辑:程序博客网 时间:2024/04/20 06:15

从前一直从事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{ //省略 @Overridepublic 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;} @Overridepublic void controlMoved(ControlEvent e) {    //ignore method}


原理说明:

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



 

原创粉丝点击