论坛首页 Java企业应用论坛

用RCP实现MSN风格的登录窗口

浏览 12221 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2006-12-26  
需要以下的对象:
LoginDialog,用于展示状态,
LoginListener,用于监听登录状态,并根据不同的情况改变LoginDialog的显示
LoginAction,用于执行登录的业务逻辑,并且根据不同的结果来fire不同的动作。

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

下面是代码片段:

Application:


 
  1. public class Application implements IPlatformRunnable {  
  2.        
  3.     /* 
  4.      * (non-Javadoc) 
  5.      *  
  6.      * @see org.eclipse.core.runtime.IPlatformRunnable#run(java.lang.Object) 
  7.      */  
  8.     public Object run(Object args) throws Exception {  
  9.   
  10.         try {  
  11.   
  12.             TestLoginDialog dialog = new TestLoginDialog(Display.getCurrent()  
  13.                     .getActiveShell());  
  14.             LoginListener loginListener = new LoginListenerImpl(dialog);  
  15.             LoginAction action = new LoginAction("login");  
  16.             action.addLoginListener(loginListener);  
  17.             dialog.setLoginAction(action);  
  18.   
  19.             if (dialog.open() != Window.OK) {  
  20.                 return IPlatformRunnable.EXIT_OK;  
  21.             }  
  22.             int returnCode = PlatformUI.createAndRunWorkbench(display,  
  23.                     new ApplicationWorkbenchAdvisor());  
  24.   
  25.             if (returnCode == PlatformUI.RETURN_RESTART) {  
  26.                 return IPlatformRunnable.EXIT_RESTART;  
  27.             }  
  28.             return IPlatformRunnable.EXIT_OK;  
  29.         } finally {  
  30.             display.dispose();  
  31.         }  
  32.     }  
  33. }  


LoginListener:


 
  1. public interface LoginListener extends EventListener{  
  2.     public void loginError(String message);  
  3.   
  4.     public void loginComplete();  
  5.   
  6.     public void loginCanceled();  
  7.       
  8.     public void loginStarted();  
  9.       
  10. }  


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


 
  1. public class LoginAction extends Job {  
  2.     private LoginListener loginListener;  
  3.     private Session session = Session.getInstance();  
  4.   
  5.     public LoginAction(String name) {  
  6.         super(name);  
  7.     }  
  8.   
  9.     public void addLoginListener(LoginListener listener) {  
  10.         this.loginListener = listener;  
  11.     }  
  12.   
  13.     public void fireLoginComplete() {  
  14.         loginListener.loginComplete();  
  15.     }  
  16.   
  17.     public void fireLoginStarted() {  
  18.         loginListener.loginStarted();  
  19.     }  
  20.   
  21.     public void fireLoginError(String message) {  
  22.         loginListener.loginError(message);  
  23.     }  
  24.   
  25.     public void fireLoginCanceled() {  
  26.         //write cancel login logic here  
  27.         loginListener.loginCanceled();  
  28.     }  
  29.   
  30.     @Override  
  31.     protected IStatus run(IProgressMonitor monitor) {  
  32.         login();  
  33.         return Status.OK_STATUS;  
  34.     }  
  35.   
  36.     public boolean login() {  
  37.         fireLoginStarted();  
  38.   
  39.         if (//网络连接失败) {  
  40.             fireLoginError(Messages.getString("Session.connectionFailed"));  
  41.         } else {  
  42.             if (//登录失败) {  
  43.             fireLoginError(Messages.getString("Session.loginFailed"));  
  44.             } else {  
  45.                 session.setAuthenticated(true);  
  46.                 fireLoginComplete();  
  47.                 //处理登录动作  
  48.             }  
  49.         }  
  50.         return session.isAuthenticated();  
  51.     }  
  52.   
  53. }  

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方法就可以了。

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


 
  1. /* 
  2.  * to create login button  
  3.  */  
  4. public static int LOGIN_ID = 9527;  


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


 
  1. @Override  
  2. protected void buttonPressed(int buttonId) {  
  3.     if (buttonId == LOGIN_ID) {  
  4.         loginPressed();  
  5.     }  
  6.     super.buttonPressed(buttonId);  
  7. }  


 
  1. protected void loginPressed() {  
  2.     //...  
  3.     loginAction.schedule();  
  4. }  

然后是LoginListener的实现类:


 
  1. public class LoginListenerImpl implements LoginListener {  
  2.     private Display display;  
  3.     //login dialog  
  4.     private TestLoginDialog dialog;  
  5.     //image to show on login failed  
  6.     private Image errorMessageImage = AbstractUIPlugin  
  7.             .imageDescriptorFromPlugin(Application.PLUGIN_ID,  
  8.                     IImageKeys.crodoTitleImage).createImage();  
  9.     //error message area background  
  10.     private Color errorMessageBackground = new Color(null2552550);  
  11.   
  12.     public LoginListenerImpl(TestLoginDialog dialog) {  
  13.         this.dialog = dialog;  
  14.         display = Display.getCurrent();  
  15.     }  
  16.   
  17.     //因为这里需要在非UI线程中更新UI,所以要用display.syncExec()方法。  
  18.     public void loginCanceled() {  
  19.         display.syncExec(new Runnable() {  
  20.             public void run() {  
  21.                 dialog.getStackLayout().topControl = dialog  
  22.                         .getLoginInfoComposite();  
  23.                 dialog.getStackLayoutComposite().layout();  
  24.                 dialog.animate();  
  25.                 dialog.getButtonBar().setVisible(true);  
  26.             }  
  27.         });  
  28.     }  
  29.   
  30.     public void loginComplete() {  
  31.         display.syncExec(new Runnable() {  
  32.             @SuppressWarnings("deprecation")  
  33.             public void run() {  
  34.                 //我知道Thread.stop()方法已经被废弃,但是暂时没想到什么方法来中止  
  35.                 //就暂时这样子用了,还请大家指教!  
  36.                 dialog.getAnimateThread().stop();  
  37.                 dialog.okPressed();  
  38.             }  
  39.         });  
  40.     }  
  41.   
  42.     public void loginError(final String message) {  
  43.         display.syncExec(new Runnable() {  
  44.             public void run() {  
  45.                 dialog.getErrorMessageLabel().setText(message);  
  46.                 dialog.getErrorMessageLabel().setImage(errorMessageImage);  
  47.                 dialog.getErrorMessageLabel().setBackground(  
  48.                         errorMessageBackground);  
  49.                 dialog.getStackLayout().topControl = dialog  
  50.                         .getLoginInfoComposite();  
  51.                 dialog.getStackLayoutComposite().layout();  
  52.                 dialog.animate();  
  53.                 dialog.getButtonBar().setVisible(true);  
  54.             }  
  55.         });  
  56.     }  
  57.   
  58.     public void loginStarted() {  
  59.         display.syncExec(new Runnable() {  
  60.             public void run() {  
  61.                 dialog.getStackLayout().topControl = dialog  
  62.                         .getLoginAnimaComposite();  
  63.                 dialog.getStackLayoutComposite().layout();  
  64.                 dialog.animate();  
  65.                 dialog.getButtonBar().setVisible(false);  
  66.             }  
  67.         });  
  68.     }  
   发表时间:2006-12-26  
现在线程的中断实际上是自己负责了,
定一个中断标志的成员变量,然后在运行中检查这个标志,
如果为真则退出循环之类的。

class TT extends Runnable {
  private int flag=1;
  public void run() {
    while (flag == 1) {
       try {
          Thread.sleep(10000);
       }catch (Exception e) {
       }
    }
  }
  public void stopThread() {
    flag = 0;
  }
}
0 请登录后投票
   发表时间:2006-12-26  
哦,是这个样子的啊,看到过这样的实现,但是不知道为什么一直没看懂,现在明白啦:)谢谢!
0 请登录后投票
   发表时间:2007-01-24  
你好,我现在也在进行RCP的开发,也想实现像你这样的登录界面,但是我把我的LoginDialog放到Application中的时候就报错,我的LoginDialog实现的是jface.Dialog,请教一下这是怎么回事?谢谢
0 请登录后投票
   发表时间:2007-01-24  

[quote="pirateship"]你好,我现在也在进行RCP的开发,也想实现像你这样的登录界面,但是我把我的LoginDialog放到Application中的时候就报错,我的LoginDialog实现的是jface.Dialog,请教一下这是怎么回事?谢谢[/quote]

你可以试一下在自己的ApplicationWorkbenchAdvisor里重写openwindows。

0 请登录后投票
   发表时间:2007-01-25  
。。。
0 请登录后投票
   发表时间:2007-01-25  
[quote="pirateship"]你好,我现在也在进行RCP的开发,也想实现像你这样的登录界面,但是我把我的LoginDialog放到Application中的时候就报错,我的LoginDialog实现的是jface.Dialog,请教一下这是怎么回事?谢谢[/quote]

贴一下代码啊,要不然我怎么知道怎么回事....
0 请登录后投票
   发表时间:2007-06-05  
楼上是在做梦么?
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics