posts - 28, comments - 27, trackbacks - 0, articles - 0
  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理
需要以下的对象:
LoginDialog,用于展示状态,
LoginListener,用于监听登录状态,并根据不同的情况改变LoginDialog的显示
LoginAction,用于执行登录的业务逻辑,并且根据不同的结果来fire不同的动作。

状态一共有以下几种:
1。登录中
2。登录成功
3。登录失败
  3.1 连接失败
  3.2 用户名密码错误
  3.3 .....
4。用户取消登录

下面是代码片段:

Application;

public class Application implements IPlatformRunnable {
 
   
    
/*
     * (non-Javadoc)
     * 
     * @see org.eclipse.core.runtime.IPlatformRunnable#run(java.lang.Object)
     
*/
    
public Object run(Object args) throws Exception {

        
try {

            TestLoginDialog dialog = new TestLoginDialog(Display.getCurrent()
                    .getActiveShell());
            LoginListener loginListener 
= new LoginListenerImpl(dialog);
            LoginAction action 
= new LoginAction("login");
            action.addLoginListener(loginListener);
            dialog.setLoginAction(action);

            
if (dialog.open() != Window.OK) {
                
return IPlatformRunnable.EXIT_OK;
            }
            
int returnCode = PlatformUI.createAndRunWorkbench(display,
                    
new ApplicationWorkbenchAdvisor());

            
if (returnCode == PlatformUI.RETURN_RESTART) {
                
return IPlatformRunnable.EXIT_RESTART;
            }
            
return IPlatformRunnable.EXIT_OK;
        } 
finally {
            display.dispose();
        }
    }
}


LoginListener:

public interface LoginListener extends EventListener{
    
public void loginError(String message);

    
public void loginComplete();

    
public void loginCanceled();
    
    
public void loginStarted();
    
}


LoginAction:这里要用到Job,因为登录的逻辑处理必须要在异步线程中来做,否则UI就会停住的。

public class LoginAction extends Job {
    
private LoginListener loginListener;
    
private Session session = Session.getInstance();

    
public LoginAction(String name) {
        
super(name);
    }

    
public void addLoginListener(LoginListener listener) {
        
this.loginListener = listener;
    }

    
public void fireLoginComplete() {
        loginListener.loginComplete();
    }

    
public void fireLoginStarted() {
        loginListener.loginStarted();
    }

    
public void fireLoginError(String message) {
        loginListener.loginError(message);
    }

    
public void fireLoginCanceled() {
        //write cancel login logic here
        loginListener.loginCanceled();
    }

    @Override
    
protected IStatus run(IProgressMonitor monitor) {
        login();
        
return Status.OK_STATUS;
    }

    
public boolean login() {
        fireLoginStarted();

        if (//网络连接失败) {
           
fireLoginError(Messages.getString("Session.connectionFailed"));
        } 
else {
            
if (//登录失败) {
           
fireLoginError(Messages.getString("Session.loginFailed"));
            } 
else {
                session.setAuthenticated(
true);
                fireLoginComplete();
                //处理登录动作
            }
        }
        
return session.isAuthenticated();
    }

}


LoginDialog:

这里用到了StackLayout,因为在登录的过程中,需要在显示用户名/密码的位置上,显示gif动画,所以在createDialogArea的时候,要创建一个主Composite,然后将其layout设置为StackLayout,然后创建两个Composite,将其parent都设置为主Composite,新创建的两个我将其命名为loginInfoComposite和loginAnimaComposite,顾名思义,一个用来显示登录信息,一个用来显示登录动画。

关于如何显示gif,我在这里就不多说了,因为SWT Snippet和Eclipse的SWT Example里面都有对应的例子,我在这里推荐大家去参考一下SWT Example,因为那里面是用Canvas来绘图的,这也是我们所需要的。

在使用StackLayout的时候要注意,当我们使用stackLayout.topControl = xxx的时候,还要调用stackLayout.layout()方法,否则会不起作用。

还有就是因为在登录的过程中,按钮栏应该是不可见的,但是Dialog的getButtonBar方法是protected的,所以就重写了这个方法,声明为public,返回super.getButtonBar(),虽然源码的注释中写着这个方法不应该重写,但是我想,这样子应该没问题吧。

另外,在绘制gif的下方添加一个按钮,并且addSelectionListener,当SelectionEvent发生的时候,就去触发loginAction的fireCancel方法就可以了。

细节就不描述了,下面是一些个人认为比较关键的代码片段:

    /*
     * to create login button 
     
*/
    
public static int LOGIN_ID = 9527;


    protected void createButtonsForButtonBar(Composite parent) {
        createButton(parent, LOGIN_ID, Messages
                .getString(
"LoginDialog.loginbutton"), true); ]
        createButton(parent, IDialogConstants.CANCEL_ID, Messages
                .getString(
"LoginDialog.cancelbutton"), false);
    }


    @Override
    
protected void buttonPressed(int buttonId) {
        
if (buttonId == LOGIN_ID) {
            loginPressed();
        }
        
super.buttonPressed(buttonId);
    }


    protected void loginPressed() {
        //...
        loginAction.schedule();
    }

然后是LoginListener的实现类:

public class LoginListenerImpl implements LoginListener {
    
private Display display;
    
//login dialog
    private TestLoginDialog dialog;
    
//image to show on login failed
    private Image errorMessageImage = AbstractUIPlugin
            .imageDescriptorFromPlugin(Application.PLUGIN_ID,
                    IImageKeys.crodoTitleImage).createImage();
    
//error message area background
    private Color errorMessageBackground = new Color(null2552550);

    
public LoginListenerImpl(TestLoginDialog dialog) {
        
this.dialog = dialog;
        display 
= Display.getCurrent();
    }

    //因为这里需要在非UI线程中更新UI,所以要用display.syncExec()方法。
    public void loginCanceled() {
        display.syncExec(
new Runnable() {
            
public void run() {
                dialog.getStackLayout().topControl 
= dialog
                        .getLoginInfoComposite();
                dialog.getStackLayoutComposite().layout();
                dialog.animate();
                dialog.getButtonBar().setVisible(
true);
            }
        });
    }

    
public void loginComplete() {
        display.syncExec(
new Runnable() {
            @SuppressWarnings(
"deprecation")
            
public void run() {
                //我知道Thread.stop()方法已经被废弃,但是暂时没想到什么方法来中止
                //就暂时这样子用了,还请大家指教!
                dialog.getAnimateThread().stop();
                dialog.okPressed();
            }
        });
    }

    
public void loginError(final String message) {
        display.syncExec(
new Runnable() {
            
public void run() {
                dialog.getErrorMessageLabel().setText(message);
                dialog.getErrorMessageLabel().setImage(errorMessageImage);
                dialog.getErrorMessageLabel().setBackground(
                        errorMessageBackground);
                dialog.getStackLayout().topControl 
= dialog
                        .getLoginInfoComposite();
                dialog.getStackLayoutComposite().layout();
                dialog.animate();
                dialog.getButtonBar().setVisible(
true);
            }
        });
    }

    
public void loginStarted() {
        display.syncExec(
new Runnable() {
            
public void run() {
                dialog.getStackLayout().topControl 
= dialog
                        .getLoginAnimaComposite();
                dialog.getStackLayoutComposite().layout();
                dialog.animate();
                dialog.getButtonBar().setVisible(
false);
            }
        });
    }


评论

# re: [rcp系列]用RCP实现MSN风格的登录窗口  回复  更多评论   

2006-09-27 10:15 by 123bingbing
想学编程?来www.mylinux.com吧,这里将成为你成长的新起点!

只有注册用户登录后才能发表评论。


网站导航: