zoukankan      html  css  js  c++  java
  • SWT的TitleAreaDialog详解

    转自:http://www.cnblogs.com/AllenYoung/archive/2006/10/05/521805.html

    Dialog是SWT和JFace的一个重要的组成部分,我们在开发Plug-in或RCP的时候也经常会用到它们。这篇随笔不会介绍 SWT的Dialog,因为我想很多人都已经非常熟悉它了。在这里,我要讨论的是JFace的Dialog,或者更进一步说是JFace的 TitleAreaDialog。什么是TitleAreaDialog呢?想想我们常常用到的New XX Wizard就知道了。在我们创建一个Java Project或Class的时候,我们所使用的Wizard其实就是由TitleAreaDialog构成的。这种Dialog有如下所示的 TitleArea和一个标准的Button Bar:

           
                                        正常的TitleArea                                                                                                               带有错误信息的TitleArea


                                        标准的Button Bar

    这种GUI的表现力要比SWT的Dialog强很多,而且JFace为该 Dialog封装了很多东西,这也使开发工作变得更加简单,所以我极力推荐使用TitleAreaDialog。那么让我们来看一个最基本的 TitleAreaDialog:

    import org.eclipse.jface.dialogs.IDialogConstants;
    import org.eclipse.jface.dialogs.TitleAreaDialog;
    import org.eclipse.swt.SWT;
    import org.eclipse.swt.graphics.Point;
    import org.eclipse.swt.layout.GridData;
    import org.eclipse.swt.widgets.Composite;
    import org.eclipse.swt.widgets.Control;
    import org.eclipse.swt.widgets.Shell;
    import org.jthin.jpssp.ide.configuration.Activator;

    public class MyTitleAreaDialog extends TitleAreaDialog {

        
    /**
         * Create the dialog
         * 
         * 
    @param parentShell
         */

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

        
    /*
         * (non-Javadoc)
         * 
         * @see org.eclipse.jface.dialogs.TitleAreaDialog#createDialogArea(org.eclipse.swt.widgets.Composite)
         */

        
    protected Control createDialogArea(Composite parent) {
            Composite area = (Composite) 
    super.createDialogArea(parent);
            Composite container = 
    new Composite(area, SWT.NONE);
            container.setLayoutData(
    new GridData(GridData.FILL_BOTH));

            
    // TitleArea中的Title
            setTitle("My TitleAreaDialog");

            
    // TitleArea中的Message
            setMessage("This is a simple TitleAreaDialog example.");

            // TitleArea中的Image
            setTitleImage(ResourceManager.getPluginImage(Activator.getDefault(), "icons/Neptune.png"));

            
    return area;
        }

        
    /*
         * (non-Javadoc)
         * 
         * @see org.eclipse.jface.dialogs.Dialog#createButtonsForButtonBar(org.eclipse.swt.widgets.Composite)
         */

        
    protected void createButtonsForButtonBar(Composite parent) {
            createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, 
    true);
            createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, 
    false);
        }

        
    /*
         * (non-Javadoc)
         * 
         * @see org.eclipse.jface.dialogs.TitleAreaDialog#getInitialSize()
         */

        
    protected Point getInitialSize() {
            
    return new Point(500, 375);
        }

        
    /*
         * (non-Javadoc)
         * 
         * @see org.eclipse.jface.window.Window#configureShell(org.eclipse.swt.widgets.Shell)
         */

        
    protected void configureShell(Shell newShell) {
            
    super.configureShell(newShell);

            
    // Dialog Title
            newShell.setText("Test TitleAreaDialog Title");

            
    // Dialog Icon
            newShell.setImage(ResourceManager.getPluginImage(Activator.getDefault(), "icons/Neptune.png"));
        }

    }


    这段代码非常容易理解,从方法签名中可以看出每个方法做了什么事情。注意createButtonsForButtonBar方法,其中用createButton方法创建了OK和Cancel这两个Button,并且把Button的默认点击事件也写好了,就是关闭该 Dialog。ResourceManager.getPluginImage是我自己编写的获得图片的helper method,这里就不讨论其实现了。这段代码会产生如下的Dialog:



    有趣的是,我在这里故意使用了一个128×128的大图标, TitleAreaDialog不会自动缩小或裁减Image,而是调整TitleArea的大小来适应Image。

    接下来我们要为OK Button编写我们自己的事件,例如把用户在Dialog中的输入保存到某处。有人可能会想到为OK Button添加SelectionListener,但实际上这样做是不对的,因为OK Button是JFace为Dialog封装好了的,同时JFace也提供了响应的callback:

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.jface.dialogs.Dialog#okPressed()
     
    */
    protected void okPressed() {
        
    // implement your own function here
        super.okPressed();
    }


    我们可以在这里实现我们自己的事件,不过最后一定要调用super.okPressed方法,否则Dialog就不会关闭了。 

    OK,以上就是TitleAreaDialog的基本Framework,非常容易理解,下面我们就来在 TitleArea中动态设置一些信息。你可以把这个scenario想象成在用户输入的同时提示用户输入的合法性。TitleAreaDialog提供了好3个方法可以动态设置TitleArea信息,具体如下:

    • public void setErrorMessage(String newErrorMessage):显示传入的错误信息。(我们把用这个方法设置的信息叫做error message。)当前显示的信息会被保存起来,等到error message清空之后会再次显示,而清空error message要传入null,而不是传入空字符串。
    • setMessage(String newMessage):显示传入的信息,等同于setMessage(String newMessage, IMessageProvider.NONE)。如果当前显示的是error message,那么newMessage会被保存起来,等到error message清空后再显示。
    • setMessage(String newMessage, int newType):显示传入的信息,并显示指定的信息类型。可用的类型有NONE、INFORMATION、WARNING和ERROR。需要注意的是, setMessage(String newMessage, int IMessageProvider.ERROR)和setErrorMessage(String newErrorMessage)并不相同。后者会覆盖当前的任何信息,而前者只会覆盖当前的非error message,不会影响到error message(也就是说当error message清空后才会显示)。

    这样,我们就可以为一些文本框添加ModifyListener,然后在其中设置TitleArea的信息了。

    接着,再让我们来看看Button Bar。有些时候,我们希望把OK和Cancel这种默认的Button放置在Button Bar的右侧,而把其他Button放置在Button Bar的左侧,如下图中的Customize... Button:



    这又如何实现呢?有人可能想到在 createButtonsForButtonBar方法中做一些手脚,但是遗憾的是这行不通,我们真正要覆写的是createButtonBar方法,下面是一个简单的例子:

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.jface.dialogs.TrayDialog#createButtonBar(org.eclipse.swt.widgets.Composite)
     
    */
    protected Control createButtonBar(Composite parent) {
        Composite composite 
    = new Composite(parent, SWT.NONE);
        GridLayout layout 
    = new GridLayout();
        layout.numColumns 
    = 0;
        layout.marginHeight 
    = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN);
        layout.marginWidth 
    = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN);
        layout.verticalSpacing 
    = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING);
        layout.horizontalSpacing 
    = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING);

        composite.setLayout(layout);
        composite.setLayoutData(
    new GridData(GridData.FILL_HORIZONTAL));

        
    if (isHelpAvailable()) {
            createHelpControl(composite);
        }

        createButton(composite, MyConstants.IMPORT_BUTTON_ID, 
    "Import", false).addSelectionListener(new SelectionAdapter() {
            
    public void widgetSelected(SelectionEvent e) {
                MessageDialog.openInformation(MaintainModuleDialog.
    this.getShell(), "Information",
                    
    ""Import" button has not been implemented.");
            }
        });

        createButton(composite, MyConstants.EXPORT_BUTTON_ID, 
    "Export"false).addSelectionListener(new SelectionAdapter() {
            
    public void widgetSelected(SelectionEvent e) {
                MessageDialog.openInformation(MaintainModuleDialog.
    this.getShell(), "Information",
                
    ""Export" button has not been implemented.");
            }
        });

        createButton(composite, MyConstants.OTHER_BUTTON_ID, 
    "Other"false).addSelectionListener(new SelectionAdapter() {
        
        public void widgetSelected(SelectionEvent e) {
                MessageDialog.openInformation(MaintainModuleDialog.
    this.getShell(), "Information",
                
    ""Other" button has not been implemented.");
            }
        });

        Label filler 
    = new Label(composite, SWT.NONE);
        filler.setLayoutData(
    new GridData(GridData.FILL_HORIZONTAL | GridData.GRAB_HORIZONTAL));
        layout.numColumns
    ++;

        
    super.createButtonsForButtonBar(composite);

        
    return composite;
    }


    正如你所见,我们实际上创建了自己的Button Bar,然后在上面添加了3个Button:Import、Export和Other,最后 super.createButtonsForButtonBar会创建OK和Cancel Button。filler是用来在两组Button见占位的。代码中用到的两个convert方法来自 org.eclipse.jface.dialogs.Dialog类,你还可以在这个类中找到一个getButton(int)方法,它可以根据传入的 ID返回用createButton创建的Button。这些都是非常实用的方法。

    回头看一下上面那个完整的 TitleAreaDialog图片,你会看到在Dialog左下角有一个问号符号,这其实是一个Button,点击它可以显示帮助信息,当然帮助信息是由你来创建的。让我们看看Eclipse Search的TitleAreaDialog中的帮助信息吧:



    如果我们也想实现这种帮助机制,那么就要实现如下方法:

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.jface.dialogs.TrayDialog#createHelpControl(org.eclipse.swt.widgets.Composite)
     
    */
    protected Control createHelpControl(Composite parent) {
        // TODO Auto-generated method stub
        return super.createHelpControl(parent);
    }


    如果不想实现帮助机制,那么最好不要在Dialog中显示出那个问号符号,你可以覆写如下方法并永远返回false,这样就不会显示问号符号了。

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.jface.dialogs.TrayDialog#isHelpAvailable()
     
    */

    public boolean isHelpAvailable() {
        return false;
    }


    那么这个酷酷的帮助机制到底是个什么东西呢?实际上,它的学名叫做DialogTray。TitleAreaDialog继承了 
    org.eclipse.jface.dialogs.TrayDialog类,而TrayDialog就可以显示这种 DialogTray,是不是有点儿拗口呢?实际上,我们不仅仅可以添加帮助信息这一种DialogTray,还可以添加任意的DialogTray,现在就让我们动手实现一个最简单的吧。代码很简单,最主要的就是要实现一个DialogTray,代码如下:

    import org.eclipse.jface.dialogs.DialogTray;
    import org.eclipse.swt.SWT;
    import org.eclipse.swt.layout.GridData;
    import org.eclipse.swt.layout.GridLayout;
    import org.eclipse.swt.widgets.Composite;
    import org.eclipse.swt.widgets.Control;
    import org.eclipse.swt.widgets.Label;
    import org.eclipse.swt.widgets.Text;

    public class MyDialogTray extends DialogTray {

        
    /*
         * (non-Javadoc)
         * 
         * @see org.eclipse.jface.dialogs.DialogTray#createContents(org.eclipse.swt.widgets.Composite)
         
    */
        
    protected Control createContents(Composite parent) {
            Composite container 
    = new Composite(parent, SWT.NONE);
            
    final GridLayout gridLayout = new GridLayout();
            gridLayout.numColumns 
    = 2;
            container.setLayout(gridLayout);

            
    final Label label = new Label(container, SWT.NONE);
            label.setText(
    "Name:");

            
    final Text text = new Text(container, SWT.BORDER);
            text.setLayoutData(
    new GridData(SWT.FILL, SWT.CENTER, truefalse));

            
    return container;
        }

    }


    我们只在其中创建了一个Label和一个Text,这就足够了。最后,我们为MyTitleAreaDialog添加两个Button,用来打开和关闭MyDialogTray,代码如下:

    final Button openTrayButton = new Button(container, SWT.NONE);
    openTrayButton.setText(
    "Open Tray");

    final Button closeTrayButton = new Button(container, SWT.NONE);
    closeTrayButton.setText(
    "Close Tray");
    closeTrayButton.setEnabled(
    false);

    openTrayButton.addSelectionListener(
    new SelectionAdapter() {
        public void widgetSelected(final SelectionEvent e) {
            // this method is from TrayDialog
            openTray(new MyDialogTray());
            openTrayButton.setEnabled(
    false);
            closeTrayButton.setEnabled(
    true);
        }
    });

    closeTrayButton.addSelectionListener(
    new SelectionAdapter() {
        
    public void widgetSelected(final SelectionEvent e) {
            
    // this method is from TrayDialog
            closeTray();
            openTrayButton.setEnabled(
    true);
            closeTrayButton.setEnabled(
    false);
        }
    });


    最后我们会得到如下对话框:



    好了,就讲这么多吧。如果能把这些东东适当地用在你的Application中,那么效果一定非常棒。

  • 相关阅读:
    js遍历删除对象的key
    MYBATIS XML SQL 结果为MAP类型时,KEY为大小问题解决
    Ubuntu SSH 失败
    Navicat 连接 Oracle Docker容器镜像报错:TNS:listener: all appropriate instances are blocking new connections
    Mybatis 定义 Oracle 存储过程,并获取存储输出字符串信息
    python基础之---else(十)
    python基础之---循环简介(九)
    python基础之---条件语句(八)
    python基础之---运算符(七)
    python基础之---转换数据类型(六)
  • 原文地址:https://www.cnblogs.com/wangjiyuan/p/titlearea.html
Copyright © 2011-2022 走看看