`
kylixs
  • 浏览: 65664 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

Swing Application Framework 学习笔记:@Action绑定的函数调用及参数

阅读更多

jdesktop的Application Framework -- Java 桌面应用程序的一个框架

 

 

使用@Action绑定事件到某个函数时,可以设置若干参数,函数被框架执行的时候将填充这些参数。下面是从源码中拷来的:

 

1、Action的入口函数:

如果不是代理的action就执行noProxyActionPerformed(actionEvent);   

 

    public void actionPerformed(ActionEvent actionEvent) {
	javax.swing.Action proxy = getProxy();
	if (proxy != null) {
	    actionEvent.setSource(getProxySource());
	    proxy.actionPerformed(actionEvent);
	}
	else if (actionMethod != null) {
	    noProxyActionPerformed(actionEvent);    
	}
    }

 

 

2、执行事件绑定的函数:

 

    private void noProxyActionPerformed(ActionEvent actionEvent) {
	Object taskObject = null;

	/* Create the arguments array for actionMethod by 
	 * calling getActionArgument() for each parameter.
	 */
	Annotation[][] allPAnnotations = actionMethod.getParameterAnnotations();
	Class<?>[] pTypes = actionMethod.getParameterTypes();
	Object[] arguments = new Object[pTypes.length];
	for(int i = 0; i < pTypes.length; i++) {
	    String pKey = null;
	    for(Annotation pAnnotation : allPAnnotations[i]) {
		if (pAnnotation instanceof Action.Parameter) {
		    pKey = ((Action.Parameter)pAnnotation).value();
		    break;
		}
	    }
	    arguments[i] = getActionArgument(pTypes[i], pKey, actionEvent);
	}

	/* Call target.actionMethod(arguments).  If the return value
	 * is a Task, then execute it.
	 */
	try {
	    Object target = appAM.getActionsObject();
	    taskObject = actionMethod.invoke(target, arguments);
	}
	catch (Exception e) {
	    actionFailed(actionEvent, e);
	}

	if (taskObject instanceof Task) {
	    Task task = (Task)taskObject;
            if (task.getInputBlocker() == null) {
                task.setInputBlocker(createInputBlocker(task, actionEvent));
            }
	    ApplicationContext ctx = appAM.getContext();
	    ctx.getTaskService().execute(task);
	}
    }

 

 

 

3、获取调用参数的方法:

 

Object org.jdesktop.application.ApplicationAction.getActionArgument(Class pType, String pKey, ActionEvent actionEvent)
 

Provides parameter values to @Action methods. By default, parameter values are selected based exclusively on their type:

Parameter TypeParameter Value
ActionEvent actionEvent
javax.swing.Action this ApplicationAction object
ActionMap the ActionMap that contains this Action
ResourceMap the ResourceMap of the the ActionMap that contains this Action
ApplicationContext the value of ApplicationContext.getInstance()

ApplicationAction subclasses may also select values based on the value of the Action.Parameter annotation, which is passed along as the pKey argument to this method:

 @Action public void doAction(@Action.Parameter("myKey") String myParameter) {
    // The value of myParameter is computed by:
    // getActionArgument(String.class, "myKey", actionEvent)
 }
 

If pType and pKey aren't recognized, this method calls actionFailed with an IllegalArgumentException.

Parameters:
pType parameter type
pKey the value of the @Action.Parameter annotation
actionEvent the ActionEvent that trigged this Action

 

    protected Object getActionArgument(Class pType, String pKey, ActionEvent actionEvent) {
	Object argument = null;
	if (pType == ActionEvent.class) {
	    argument = actionEvent;
	}
	else if (pType == javax.swing.Action.class) {
	    argument =  this;
	}
	else if (pType == ActionMap.class) {
	    argument = appAM;
	}
	else if (pType == ResourceMap.class) {
	    argument = resourceMap;
	}
	else if (pType == ApplicationContext.class) {
	    argument = appAM.getContext();
	}
	else if (pType == Application.class) {
	    argument = appAM.getContext().getApplication();
	}
	else {
	    Exception e = new IllegalArgumentException("unrecognized @Action method parameter");
	    actionFailed(actionEvent, e);
	}
	return argument;
    }

 

 

 

代码示例:

1.没有参数

    @Action
    public void search() {

        // your code...
    }

 

2. 带ActionEvent参数,获得参数的能力等同写在ActionListener里面了

    @Action
    public void search(ActionEvent e) {

        // your code...
    }

 

3.带ResourceMap,这个比较实用,可以直接取到这个类的资源映射表

    @Action
    public void search(ResourceMap resourceMap, ActionEvent e) {

        // your code...
    }

补充一下,一个Application可以有多个Resource文件。如果存在一个和类同名的properties文件,则这个被认为是此类的资源文件,否则使用这个Application的资源文件。这种组织方式比较好,可以将资源分散到调用类的资源文件里定义,方便维护,结构清晰。

 

4.其它参数类似,只要类型匹配就行,顺序没关系!!

ApplicationAction类还不支持@Action.Parameter,程序中没处理,但这个可以很方便扩展。

 

 

总结:

使用@Action绑定事件到某个函数,这不但可以获取原来所需的参数,而且还可以方便的获得Application的相关参数,也支持扩展。

极力推荐使用这种方式编写Swing的事件处理,再也不用写n个Action了,或是那些看到麻木的new ActionListener(ActionEvent e){......}

2
0
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics