java SWT 锁住焦点

出于种种原因,SWT的底层事件机制事实上是有很多限制的,其中一个限制就是利用常规方式无法将focus锁定在一个控件里,例如一个文本框,我们要验证用户输入的文字为hello时才让用户的focus离开文本框,否则 就一直把focus锁定在文本框中,这虽然有点霸道,但是有时确实是业务的需求,不少人在eclipse newsgroup上提出这样的需求:

以下模式的代码可能是你想到的第一个解决方案,也就是我前面提到的所谓常规方法:

import  org.eclipse.swt.SWT;
import  org.eclipse.swt.events.FocusEvent;
import  org.eclipse.swt.events.FocusListener;
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  FocusLock  {

    
public static void main(String args[]) {
        Display display 
= new Display();
        
final Shell shell = new Shell(display);

        shell.setSize(
500500);
        shell.setLayout(
new GridLayout());

        FocusListener listener 
= new FocusListener() {
            
public void focusGained(FocusEvent e) {

            }


            
public void focusLost(FocusEvent e) {
                
final Text textField = (Text) e.widget;
                
if (!textField.getText().equals("hello")) {
                    
                    
// let's try to set the focus back
                    boolean isLockSuccessful = textField.setFocus();
                    System.out.println(isLockSuccessful);
                }

            }

        }
;

        Text txt 
= new Text(shell, SWT.BORDER);
        txt.pack();
        txt.addFocusListener(listener);
        
// Create another text
        Text txt1 = new Text(shell, SWT.BORDER);
        txt1.addFocusListener(listener);

        shell.open();
        
while (!shell.isDisposed())
            
if (!display.readAndDispatch())
                display.sleep();
        display.dispose();
    }


}


测试以上代码你会发现,focus根本没有锁住,并且屏幕上打出许多false。这是因为当代码运行到textField.setFocus()时,这个textField事实上还是有焦点的,对仍然有焦点的控件调用setFocus必然失败,结果返回一个false,focus自然不会被锁住啦。呵呵,失望吧,如果在Swing这可是小儿科的东西,到SWT里咋就这么难呢?主要是因为SWT与Swing的实现机理不同,它使用的控件都是重量级的OS native控件,所以自然会有这样那样的限制。别急,解决方案来啦!试试我写的下面这个FocusLocker吧,这个小东西好用着呢,不但能锁住focus,还能防止两个同时要求锁住focus的控件相互争抢focus导致死循环(例如focus在一个要求锁住focus的控件上,用户又去点了另外一个要求锁住focus的控件,这时就会出现这种情况)。下面是源代码:

import  org.eclipse.jface.dialogs.Dialog;
import  org.eclipse.swt.SWT;
import  org.eclipse.swt.widgets.Control;
import  org.eclipse.swt.widgets.Display;
import  org.eclipse.swt.widgets.Shell;

public   class  FocusLocker  extends  Dialog  {
    
    
public static boolean focusLocked = false;
    
    
protected Control controlToLock; 
    
    
public FocusLocker(Control controlToLock) {
        
super(Display.getCurrent().getActiveShell());
        
this.setBlockOnOpen(false);
        
this.controlToLock = controlToLock;
    }


    
public FocusLocker(Shell parentShell) {
        
super(parentShell);
        
    }


    @Override
    
protected void configureShell(Shell newShell) {
        
super.configureShell(newShell);
        newShell.setBounds(
0000);
    }


    
protected void setShellStyle(int newShellStyle) {
        
super.setShellStyle(newShellStyle | SWT.NO_TRIM);
    }

    
    
public void lockFocus() {
        
if (!focusLocked) {
            focusLocked 
= true;
            
this.open();
            
this.close();
            controlToLock.setFocus();
            focusLocked 
= false;
        }

        
    }


}


让我们来试一下这个小东西吧,还是刚才那段代码,我们只改锁focus的部分,注意,两个Text都是要求锁Focus的,试试它们有没有冲突:

import  org.eclipse.swt.SWT;
import  org.eclipse.swt.events.FocusEvent;
import  org.eclipse.swt.events.FocusListener;
import  org.eclipse.swt.layout.GridLayout;
import  org.eclipse.swt.widgets.Control;
import  org.eclipse.swt.widgets.Display;
import  org.eclipse.swt.widgets.Shell;
import  org.eclipse.swt.widgets.Text;

import  com.ibm.btt.rcp.ibranch.util.FocusLocker;

public   class  FocusLock  {

    
public static void main(String args[]) {
        Display display 
= new Display();
        
final Shell shell = new Shell(display);

        shell.setSize(
500500);
        shell.setLayout(
new GridLayout());

        FocusListener listener 
= new FocusListener() {
            
public void focusGained(FocusEvent e) {

            }


            
public void focusLost(FocusEvent e) {
                
final Text textField = (Text) e.widget;
                
if (!textField.getText().equals("hello")) {
                    
                    
// let's try my little invention
                    FocusLocker locker= new FocusLocker((Control)e.widget);
                    locker.lockFocus();

                }

            }

        }
;

        Text txt 
= new Text(shell, SWT.BORDER);
        txt.pack();
        txt.addFocusListener(listener);
        
// Create another text
        Text txt1 = new Text(shell, SWT.BORDER);
        txt1.addFocusListener(listener);

        shell.open();
        
while (!shell.isDisposed())
            
if (!display.readAndDispatch())
                display.sleep();
        display.dispose();
    }


}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值