posts - 28, comments - 27, trackbacks - 0, articles - 0
  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

首先是一个效果图:

login.JPG

为了不违反保密协议,偶在这里把logo和相关的东西都涂掉了,希望不会让人觉得难看....

ok,下面就开始讲述偶的coding过程:

首先捏,Dialog是分为三部分的,Window Title Bar,Content Area和Button Bar

这里的Window Title Bar素很难改动滴,偶也米改....而接下来的ContentArea和ButtonBar因为素分成两截滴,所以就要把一张背景图片拆成两截,分别设置成ContentArea和ButtonBar的背景图片鸟~~~
    protected Control createDialogArea(Composite parent) {
        Composite composite = (Composite) super.createDialogArea(parent);
        composite.setBackgroundImage(backgroundImage);
        .......
    }

    protected Control createButtonBar(Composite parent) {
        Control composite 
= super.createButtonBar(parent);
        composite.setBackgroundImage(backgroundBtmImage);
        .......
       
return composite;
    }

当然,仅仅做到这些还是远远不够滴,不信,你看~~~

login2.JPG

看到效果了咩....接下来偶们要做滴就是解决掉背景的问题,因为这个对话框里面没有Table、Tree之类的控件,于是在createDialogArea()方法中加入一行:

composite.setBackgroundMode(SWT.INHERIT_DEFAULT);

我们再来看看改变后的效果:

login3.JPG

如上图所示,介个ContentArea的背景问题已经解决鸟,下面就素重中之重滴ButtonArea鸟~~~让我们打开Dialog的源代码,看一下createButtonBar()的部分,就可以发现里面有两行:

        GridData data = new GridData(GridData.HORIZONTAL_ALIGN_END
                
| GridData.VERTICAL_ALIGN_CENTER);
        composite.setLayoutData(data);

介样子怎么能行捏,偶们需要让介个Composite填满整个DialogArea,这样子才可以显示出整个背景图片,所以偶们就要在重写后的方法中加入下面一行代码:

composite.setLayoutData(new GridData(SWT.FILL, SWT.TOP, falsefalse));

现在让偶们再来看看运行后的结果:

login4.JPG

为什么会素介个样子捏?即使素把layout改成SWT.RIGHT,也不会改变介个结果...偶快要郁闷滴抓狂鸟.....

经过漫长滴测试,偶终于发现鸟,如果控件滴layoutData不grabExcessSpace的话,那么现在滴DialogArea的Composite实际大小就素两个Button加起来滴大小,所以无论如何也素不会居右对齐滴....介可怎么办捏.....如果去重写createButton方法滴话,那介个dialog滴代码可就太丑陋鸟....

在一个偶然滴机会下,偶终于发现鸟SWT.RIGHT_TO_LEFT !!!偶依稀见到鸟灿烂滴曙光!8过Composite的style素在创建时指定的,似乎米办法在后面覆盖,所以偶们只好整个滴把createButtonBar重写掉鸟~~~

    protected Control createButtonBar(Composite parent) {
        Composite composite 
= new Composite(parent, SWT.RIGHT_TO_LEFT
                
| SWT.NONE);
        
// create a layout with spacing and margins appropriate for the font
        
// size.
        GridLayout layout = new GridLayout();
        layout.makeColumnsEqualWidth 
= true;
        layout.marginWidth 
= convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN);
        layout.marginHeight 
= convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN);
        layout.horizontalSpacing 
= convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING);
        layout.verticalSpacing 
= convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING);
        layout.marginLeft 
= 10;
        composite.setLayout(layout);
        GridData data 
= new GridData(SWT.FILL, SWT.TOP, falsefalse);
        composite.setLayoutData(data);
        composite.setFont(parent.getFont());

        
// Add the buttons to the button bar.
        createButtonsForButtonBar(composite);
        composite.setBackgroundImage(backgroundBtmImage);
        
return composite;
    }

在上面的代码中,偶除了对偶所提到的地方进行了修改以外,还加上鸟一行: layout.marginLeft = 10;

介个素因为如果右边距过小滴话,背景图片就会被覆盖掉一些,而因为偶们用到鸟
SWT.RIGHT_TO_LEFT,所以应当设置marginLeft滴值 :-)

还有一点素8能忘记滴,就素要重写一下setButtonLayoutData(Button button)方法,因为偶们要把Button改成居右对齐:

    protected void setButtonLayoutData(Button button) {
        GridData data 
= new GridData(SWT.RIGHT, SWT.CENTER, falsefalse);
        
int widthHint = convertHorizontalDLUsToPixels(IDialogConstants.BUTTON_WIDTH);
        Point minSize 
= button.computeSize(SWT.DEFAULT, SWT.DEFAULT, true);
        data.widthHint 
= Math.max(widthHint, minSize.x);
        button.setLayoutData(data);
    }

然后再在createButtonsForButtonBar()方法中,把创建按钮的顺序改变一下,偶们就可以看到最开始滴那张美丽滴对话框鸟~~~虽然被偶涂改滴有些不美丽鸟~~~

现在还有个小小滴问题就素按钮距离底端滴黑框太近鸟~~介个素因为,介个Composite只有一行,所以要改变按钮距离底端滴距离,那么DialogArea滴大小就要跟着改变,而现在偶们滴DialogArea所需要滴背景图片还米改好,于是只有这样鸟~~~大家应该知道在哪里设置底边的边距吧?就素createButtonBar方法中滴那个layout.marginHeight =xxx :)

最后别忘了,整个对话框的高度,应该是Window Title Bar,Content Area和Button Bar三部分滴和。

偶已经说完鸟,如果觉得偶滴介篇文章对你有些帮助的朋友,请去支持一下偶们美丽可爱滴靓颖同学滴新专辑The One吧:)多谢!

posted @ 2006-10-16 18:11 小小凉粉 阅读(4189) | 评论 (12)编辑 收藏

IWorkbenchPreferenceConstants中有很多常量,用来配置preference settings,诸如:

OPEN_NEW_PERSPECTIVE——打开新视图的方式
DOCK_PERSPECTIVE_BAR——锁定
PerspectiveBar的位置
INITIAL_FAST_VIEW_BAR_LOCATION——表示fast view bar在一个fresh workspace中锁定的位置,This preference is meaningless after a workspace has been setup, since the fast view bar state is then persisted in the workbench
SHOW_TRADITIONAL_STYLE_TABS——表示是否在editor和view上显示传统的tab style
SHOW_PROGRESS_ON_STARTUP——是否在启动时显示progress
SHOW_TEXT_ON_PERSPECTIVE_BAR——是否在PerspectiveBar上显示文字

等等......

更改的时候
在RCP中的plugin.xml里,使用preferenceCustomization属性,例如:
CODE:

<extension
id="someproduct"
point="org.eclipse.core.runtime.products">
<product
  application="com.example.someproduct.application"
  name="Some Product">
  <property
    name="preferenceCustomization"
    value="plugin_customization.ini"/>

然后在ini文件中进行对应的设置

或者,
PlatformUI.getPreferenceStore().setDefault(IWorkbenchPreferenceConstants.SHOW_TRADITIONAL_STYLE_TABS,false);

posted @ 2006-10-08 10:04 小小凉粉 阅读(1238) | 评论 (1)编辑 收藏

先说一下AOSD的起源吧

传统的软件工程有一个不变的主题:对关注点的分解和局部化。将系统分解成为主要的功能模块,识别出关注点的其他问题,确保所有关注点的问题都能在代码的适当位置得到解决。但是关注点的分散和混杂又给代码编写和后期维护带来了很大的难度。
因此,必须有一种方法可以把关注点集中在一起,让系统开发者可以使用关注点自身的模块来描述每个关注点的行为。
AOSD,用以寻找软件系统中新的模块化特性,允许对系统中多个关注点进行独立描述,同时又能自动统一到系统中。

然后是一些常用的术语(from AOSD wiki):

concern(关注点):A concern is an area of interest or focus in a system. Concerns are the primary criteria for decomposing software into smaller, more manageable and comprehensible parts that have meaning to a software engineer.

crosscutting(横切):Note that crosscutting is a relationship between representations of concerns. Note also that it is a symmetric relationship. Therefore, if:

1. A is a representation of one a concern,
2. B is a representation of another concern, and
3. A crosscuts B,

then B also crosscuts A.

This means that the term "crosscutting concerns" is often misused in two ways: To talk about a single concern, and to talk about concerns rather than representations of concerns. Consider "synchronization is a crosscutting concern": we don't know that synchronization is crosscutting unless we know what it crosscuts. And there may be representations of the concerns involved that are not crosscutting.

aspect(方面):Aspects are one kind of concern in software development.

joint point(联接点):Join points are those elements of the programming language semantics which the aspects coordinate with. Nowadays, there are various join point models around and still new under development. They heavily depend on the underlying programming language and AO language.

In a number of presently available AOP languages, a join point is a region in the dynamic control flow of an application. Thus a join point can for instance represent

* a call to a method,
* execution of a method,
* the event of setting a field,
* the event of handling an exception ...

Join points can be picked up by an AOP program by using pointcuts to match on them. Depending on the pointcut language the AOP language provides, it may be possible to pick up more or less of those join points. Since join points are dynamic, it may be possible to expose runtime information such as the caller or callee of a method from a join point to a matching pointcut.

advice:In a number of AOP languages, advice consists of a pointcut and a body. The body executes at join points the pointcut matches. This pointcut may expose runtime information to the advice body.

pointcut:

(from Without EJB):A set of join points,defined to specify when an advice should fire.Pointcuts are often described using either regular expressions or another wildcard syntax.

(from Wiki)In a number of AOP languages, a pointcut is a predicate over dynamic join points, meaning that given a certain dynamic join point, a pointcut can either match this join point or not (at runtime). Another view of pointcuts is often, that they represent sets of join points. A pointcut may expose runtime information to a piece of advice.

Weaving:The process of coordinating aspects and non-aspects. Weaving can be done explicitly or implicitly, and can be done at a variety of times ranging from by-hand weaving when code is written, through compile-time, post-compile time and load time, up to runtime.

Without EJB中有个例子很好的解释了一下上面的术语:

public class MyBusinessObject implements BusinessObject{
public void businessMethod1() throws UnauthorizedException{
doSecurityCheck();
}
public void businessMethod2() throws UnauthorizedException{
doSecurityCheck();
}
public void requiresNoSecurityCheck() {
}
public void doSecurityCheck() throws UnauthorizedException{
}
}

这里,安全检查就是一个aspect,需要进行安全检查的这几个方法就是join point。而由于不是所有的方法都需要进行安全检查,所以就需要用pointcut来进行匹配。

下面使用了一个interceptor来将关注点模块化:

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

public class SecurityInterceptor implements MethodInterceptor{
public Object invoke(MethodInvocation invocation)throws Throwable{
doSecurityCheck();
return invocation.proceed();
}
public void doSecurityCheck{}
}

这里的interceptor就是advice

posted @ 2006-09-27 23:51 小小凉粉 阅读(254) | 评论 (0)编辑 收藏

需要以下的对象:
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);
            }
        });
    }

posted @ 2006-09-25 19:02 小小凉粉 阅读(2121) | 评论 (1)编辑 收藏

如果使用了Eclipse3.2提供的自绘制功能来在table或者tree里面绘制图像或文字的时候,就必须在LabelProvider中,将对应column的返回值置空,同时需要记住的是,即使所有的column都使用自绘制功能的时候,也必须要给viewer提供一个LabelProvider,否则每一行的第一列上都会显示出对应Object的toString()方法的结果。

posted @ 2006-09-21 14:44 小小凉粉 阅读(1293) | 评论 (2)编辑 收藏

SMTP的连接和收发过程

a.建立TCP连接。
b.客户端发送HELO命令以标识发件人自己的身份,然后客户端发送MAIL命令服务器端正希望以OK作为响应,表明准备接收。
c.客户端发送RCPT命令,以标识该电子邮件的计划接收人,可以有多个RCPT行
d.协商结束,发送邮件,用命令DATA发送
e.以.表示结束输入内容一起发送出去
f.结束此次发送,用QUIT命令退出。

SMTP的基本命令集

HELO   向服务器标识用户身份
MAIL   初始化邮件传输mail from:
RCPT   标识单个的邮件接收人;常在MAIL命令后面可有多个rcpt to:
DATA   在单个或多个RCPT命令后,表示所有的邮件接收人已标识,初始化数据传输,以.结束。
NOOP   无操作,服务器应响应OK
RSET   重置会话,当前传输被取消
QUIT   结束会话


POP3简介

在POP3协议中有三种状态,认可状态,处理状态,和更新状态。当客户机与服务器建立联系时,一旦客户机提供了自己身份并成功确认,即由认可状态转入处理状态,在完成相应的操作后客户机发出quit命令,则进入更新状态,更新之后最后重返认可状态。

POP3基本命令集
USER username
PASS password   
STAT  请求服务器发回关于邮箱的统计资料,如邮件总数和总字节数
LIST  返回邮件数量和每个邮件的大小
RETR [Msg#] 返回由参数标识的邮件的全部文本
DELE [Msg#] 服务器将由参数标识的邮件标记为删除,由quit命令执行
RSET 服务器将重置所有标记为删除的邮件,用于撤消DELE命令
NOOP 服务器返回一个肯定的响应
QUIT 更新


class POP3Demo {
   private static String POP3Server = "pop.126.com";
    private static String USERNAME = "username";//实际应用中改成真实的用户名
    private static String PASSWORD = "password";//实际应用中改成真实的密码
    public static void main(String[] args) {
        int POP3Port = 110;
        Socket client = null;
        try {
            // 向POP3服务程序建立一个套接字连接。
            client = new Socket(POP3Demo.POP3Server, POP3Port);
            // 创建一个BufferedReader对象,以便从套接字读取输出。
            InputStream is = client.getInputStream();
            BufferedReader sockin = new BufferedReader(new InputStreamReader(is));
            // 创建一个PrintWriter对象,以便向套接字写入内容。
            OutputStream os = client.getOutputStream();
            PrintWriter sockout = new PrintWriter(os, true);
            // 显示同SMTP服务程序的握手过程。
            System.out.println("S:" + sockin.readLine());
            sockout.println("user " + POP3Demo.USERNAME);
            System.out.println("S:" + sockin.readLine());
            sockout.println("pass " + POP3Demo.PASSWORD);
            System.out.println("S:" + sockin.readLine());
            sockout.println("stat");
            String temp[] = sockin.readLine().split(" ");
            int count = Integer.parseInt(temp[1]);//得到信箱中共有多少封邮件
            for (int i = 1; i < count + 1; i++) {//依次打印出邮件的内容
                sockout.println("retr " + i);
                System.out.println("以下为第" + i + "封邮件的内容");
                while (true) {
                    String reply = sockin.readLine();
                    System.out.println(reply);
                    if (reply.toLowerCase().equals(".")) {
                        break;
                    }
                }
            }

        } catch (IOException e) {
            System.out.println(e.toString());
        } finally {
            try {
                if (client != null) {
                    client.close();
                }
            } catch (IOException e) {}
        }
    }
}

 class SMTPDemo {
    //以下三项请在使用时改成真实的信箱地址
    //并且注意,SMTPServer和receiver必须是同一个服务器
    private static String sender = "sender";
    private static String receiver = "receiver";
    private static String SMTPServer = "smtpserver";
    public static void main(String[] args) {
        int SMTPPort = 25;
        Socket client = null;
        try {
            // 向SMTP服务程序建立一个套接字连接。
            client = new Socket(SMTPDemo.SMTPServer, SMTPPort);
            // 创建一个BufferedReader对象,以便从套接字读取输出。
            InputStream is = client.getInputStream();
            BufferedReader sockin = new BufferedReader(new InputStreamReader(is));
            // 创建一个PrintWriter对象,以便向套接字写入内容。
            OutputStream os = client.getOutputStream();
            PrintWriter sockout = new PrintWriter(os, true);
            // 显示同SMTP服务程序的握手过程。
            System.out.println("S:" + sockin.readLine());
            sockout.println("helo");
            System.out.println("S:" + sockin.readLine());
            sockout.println("mail from: " + "<" + SMTPDemo.sender + ">");
            System.out.println("S:" + sockin.readLine());
            sockout.println("rcpt to: " + "<" + SMTPDemo.receiver + ">");
            System.out.println("S:" + sockin.readLine());
            sockout.println("data");
            //发送邮件标题
            sockout.println("subject: 你好");
            //发送邮件内容
            sockout.println("ni hao");
            sockout.println("wo shi li jian");
            //此处的.为特殊标记,表示邮件结束
            sockout.println(".");
            sockout.println("rset");
            sockout.println("quit");
        } catch (IOException e) {
            System.out.println(e.toString());
        } finally {
            try {
                if (client != null) {
                    client.close();
                }
            } catch (IOException e) {}
        }
    }
}


posted @ 2006-09-18 15:11 小小凉粉 阅读(2628) | 评论 (5)编辑 收藏

Design decisions:

Most platforms require that widgets be created within the context of a specific parent, so SWT requires that a parent widget be supplied as one of its constructor arguments. Another requirement of many platforms is that certain style settings must be supplied at creation time (for example, buttons can be checkboxes, radio buttons, or simple buttons and text fields can be single- or multi-line).

Style bits are represented by int constants defined in the SWT class. Styles are then OR'ed together and passed as another constructor argument to create the initial style of a widget.

SWT works directly with the native underlying graphic resources, each SWT resource consumes a GUI resource, and timely release of that resource is essential not only for your SWT application's well-being, but also for the well-being of all other GUI programs currently running. Java's garbage collection carries no timeliness guarantees, and would make a poor manager of graphic resources for SWT. So, instead, you as programmer must assume the responsibility.

Fortunately, a widget that is a child of another widget is automatically destroyed when its parent is destroyed. This means that if you properly dispose of a shell, you do not need to dispose of each of its children because they will be disposed of automatically.

----------------------------------------------------------------------------------------

Top-level classes:

Each SWT application needs a display and one or more shells (representing each window frame).

Display: The Display object represents the connection between the application-level SWT classes and the underlying windowing system implementation.

One of the most important tasks of this class is its event-handling mechanism. The Display class maintains a collection of registered event listeners, reads events from the lower-level operating-system event queue, and delivers these events to the appropriate implementations of registered listener logic.

Shell: Every window has a shell representing the window frame with which the user interacts. The Shell object represents a window—either a top-level window or a dialog window. It contains the various controls that make up the application: buttons, text boxes, tables

----------------------------------------------------------------------------------------

Control: The Control class is the abstract superclass of all the dialog and window component classes such as Button, Label, ProgressBar, Sash, Scrollable, and Slider

Composite: Taking a bottom-up view of the world, every control has a parent that is an instance of the class Composite or one of its subclasses. The class Shell, which represents the top-level windows of your application, is a subclass of Composite.

Stated another way, this time from the top down, a display contains a list of top-level shells, where each shell is the root of a tree composed of composites and controls. Composites can contain other composites, allowing the tree to have arbitrary depth. If the child of a shell is another shell, the child is commonly called a dialog shell. A dialog shell always stays in front of the parent shell.

posted @ 2006-09-18 15:09 小小凉粉 阅读(246) | 评论 (0)编辑 收藏

ModalessDialog:

public class ModalessDialog extends Dialog {
 public ModalessDialog(Shell arg0) {
  super(arg0);
  setShellStyle(SWT.SHELL_TRIM | SWT.MODELESS | SWT.RESIZE | SWT.MAX);
 }
}


程序中需要双击摄像头,然后弹出的对话框中显示摄像头所捕捉的画面,原来是这样写的:

  deviceTab.getViewer().addDoubleClickListener(
    new IDoubleClickListener() {
     public void doubleClick(DoubleClickEvent event) {
      StructuredSelection selection = (StructuredSelection) event
        .getSelection();
      DeviceDataDialog dialog = new DeviceDataDialog(event
        .getViewer().getControl().getShell());
      dialog.open();
     }
    });

但是这样子出来的对话框,会始终保持在最前端显示。后来改成

DeviceDataDialog dialog = new DeviceDataDialog(null);

就可以了
也许是因为原先的程序中,对话框和主窗口使用同一个Shell所造成的吧

posted @ 2006-09-18 15:09 小小凉粉 阅读(981) | 评论 (0)编辑 收藏

因为RCP的界面也是使用MVC模式的,于是想操作TableViewer、TreeViewer的时候,不应该直接对Viewer进行操作,而是应该操作viewer的input。修改以后,调用一下viewer.refresh()方法就可以了。

今天碰到的问题是,在一个widget中,使用

viewer.setInput(DisplayConst.publishingDevices.values());

可以顺利更新

而在另外一个widget中,使用

  viewer.setInput(DisplayConst.locationTable.get(this.getUserName()));

就不能正常更新了。

测试了半天,又想了一下才明白,viewer.setInput以后,我们只能够修改input的内容,而不能修改input这个对象内存地址的值。就和方法调用在java中只能传值调用一样了。

posted @ 2006-09-18 15:08 小小凉粉 阅读(713) | 评论 (0)编辑 收藏

为了批量发布设备,需要在一个窗口中为设备命名,设定其类型等,要用到Combo,所以就用了CellEditor

用CellEditor还是很方便的,有CheckboxCellEditor,ComboBoxCellEditor,LabelCellEditor,TextCellEditor等等。

首先把TableColumn的名称做成String数组,调用viewer.setColumnProperties()方法

然后做一个CellEditor数组,数组中的每一个CellEditor都对应着每一个Column

然后实现ICellModifier接口,做一个自己的CellModifier,并调用viewer.setCellModifier()方法

接口中有三个方法:

1.public boolean canModify(Object element, String property)
用来判断哪一个属性可写
2.public Object getValue(Object element, String property)
返回某个属性的值
3.public void modify(Object element, String property, Object value)
为某个属性赋值

昨天碰到了很多异常,情况如下:

1.ComboCellEditor 中对应的是Integer类型的值,如果用了String的话,就会有异常抛出。

2.tableviewer的input中,对象的很多属性没有赋初始值,由此而导致了在CellModifier里面调用get或者set方法时,出现了空指针异常。

3.update tableviewer。今天上午才找到table.addFocusListener方法,而且要在focusGained方法中进行更新。应该是由于编辑Cell的时候,focus从Table转移到了Cell上,所以要用focusGained方法吧。

posted @ 2006-09-18 15:08 小小凉粉 阅读(1355) | 评论 (0)编辑 收藏

仅列出标题
共3页: 上一页 1 2 3 下一页