SWT窗口范围内的Lost Focus事件的兑现

SWT窗口范围内的Lost Focus事件的实现
文章转自:http://blog.****.net/shrekmu/archive/2007/10/16/1826993.aspx
一、问题

    SWT中如果添加一个Lost Focus事件后,会发现当窗体切换、最小化窗体等事件发生的时候都会激发Lost Focus事件,这显然不过友善。传统意义上的Lost Focus事件应该是只有焦点迁移到单前窗体中的某个空间的时候才需要激发Lost Focus事件。但是由于RCP程序中,一个窗体可能包含多个View和Editor,所以这个Listener实现了当焦点迁移到指定 Composite中时,激发LostFocus事件。

二、事件代码

package study.swt.event;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.FocusListener;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;

/** *//**
 * <b>系统名称:</b>Digital Cinema心得--SWT学习与使用<br>
 * <b>技能名称:</b>监听指定范围内lost Focus事件的监听器<br>
 * <b> 处理说明:</b>SWT中如果添加一个Lost Focus事件后,会发现当窗体切换、最小化窗体等事件发生的时候都会激发 Lost Focus事件,这显然不过友善。传统意义上的Lost Focus事件应该是只有焦点迁移到单前窗体中的某个空间的时候才需要激发 Lost Focus事件。但是由于RCP程序中,一个窗体可能包含多个View和Editor,所以这个Listener实现了当焦点迁移到指定 Composite中时,激发LostFocus事件。。<br>
 * <b>变革履历:</b>2007/10/16 MuChunYu Create<br>
 * <br>
 *
 * @author Mu ChunYu
 * @version 1.0 2007/07/04 初版
 * <p>
 */
public class FocusLostListener implements FocusListener ...{
   
    /** *//** 定义取得焦点范围的Composite */
    private Composite cmpParent = null;
   
    /** *//** 所监听的控件 */
    private Control ctl = null;

    /** *//** Gained Focus事件的过滤器 */
    private Listener filter = new Listener() ...{
        /** *//** 处理事件 */
        public void handleEvent(Event event) ...{
            // 判断是否是指定Composite中的空间取得了焦点
            if (isChildOf(cmpParent, (Control) event.widget)) ...{
                if (ctl != (Control) event.widget) ...{
                    cmpParent.getDisplay().removeFilter(SWT.FocusIn, filter);
                    dcFocusLost(new FocusEvent(event));
                }
            }
        }
       
        /** *//** 判断是否之指定Composite的子控件 */
        private boolean isChildOf(Composite cmpParent1, Control ctlChild) ...{
            Composite cltParent = ctlChild.getParent();
            while (cltParent != null) ...{
                if (cltParent == cmpParent1) ...{
                    return true;
                } else ...{
                    cltParent = cltParent.getParent();
                }
            }
            return false;
        }
    };

    /** *//**
     * <b>機能概要:</b> 构造函数。<br>
     * <br>
     * <b>処理フロー:</b> <br>
     * <ul>
     * <li>保存信息
     * <li>注册Focus监听器
     * </ul>
     *
     * @param cmpParent 定义取得焦点范围的Composite
     * @param ctl 所监听的控件
     * <p>
     */
    public DCFocusLostListener(Composite cmpParent, Control ctl) ...{
        this.cmpParent = cmpParent;
        this.ctl = ctl;
        ctl.addFocusListener(this);
    }

    /** *//**
     * <b>機能概要:</b> 取得焦点事件的处理。<br>
     * <br>
     * <b>処理フロー:</b> <br>
     * <ul>
     * <li>注册取得焦点事件的过滤器
     * </ul>
     *
     * @param event Focus事件
     * @deprecated 不需要使用。
     * <p>
     */
    @Override
    public void focusGained(FocusEvent event) ...{
        registerFilter();
    }

    /** *//**
     * <b>機能概要:</b> 注册取得焦点事件的过滤器。<br>
     * <br>
     * <b>処理フロー:</b> <br>
     * <ul>
     * <li>注册取得焦点事件的过滤器
     * </ul>
     *
     * <p>
     */
    public void registerFilter() ...{
        ctl.getDisplay().removeFilter(SWT.FocusIn, filter);
        ctl.getDisplay().addFilter(SWT.FocusIn, filter);
    }
   
    /** *//**
     * <b>機能概要:</b> 失去焦点事件的处理。<br>
     * <br>
     * <b>処理フロー:</b> <br>
     * <ul>
     * <li>无处理
     * </ul>
     *
     * @param event Focus事件
     * @since 1.0
     * @deprecated 不能使用。 使用dcFocusLost(FocusEvent event)
     * <p>
     */
    @Override
    public void focusLost(FocusEvent event) ...{
    }
   
    /** *//**
     * <b>機能概要:</b> 失去焦点事件的处理。<br>
     * <br>
     *
     * @param event Focus事件
     * @since 1.0
     * <p>
     */
    public void dcFocusLost(FocusEvent event) ...{
    }
}



三、使用方式
1、监听指定容器的Lost Focus事件
// 监听指定容器的Lost Focus事件
    DCFocusLostListener listenter = new DCFocusLostListener(cmpParent, m_Control) {
        public void dcFocusLost(FocusEvent event) {
            // TODO 业务处理
        }
    };
// 如果控件已经取得了焦点,就需要手工调用registerFilter()
    listenter.registerFilter();



2、监听窗体的Lost Focus事件
// 监听窗体的Lost Focus事件
    DCFocusLostListener listenter = new DCFocusLostListener(shell, m_Control) {
        public void dcFocusLost(FocusEvent event) {
            // TODO 业务处理
        }


    };