浏览 3445 次
锁定老帖子 主题:Swing小应用(Todo-List)之三
精华帖 (0) :: 良好帖 (2) :: 新手帖 (0) :: 隐藏帖 (0)
|
|||
---|---|---|---|
作者 | 正文 | ||
发表时间:2010-04-22
最后修改:2010-04-30
前言去年9月份开发的那个小工具sTodo,只是做到了能用,但是还很不好用,比如没有定时的提醒功能,整个框架比较死板,不方便扩展,虽然设计之初就考虑要使用脚本语言进行脚本化,提供更强的定制能力,但是一直因为工作上事情太多,没有经历投入而悬停。
不明真相的可以参看以前的两篇文章:
sTodo的现状sTodo内部用了一套任务管理模块,可以做到定时提醒的功能,效果还是不错的: 虽然UI还很原始,但是基本功能都已经实现,剩下就是美化UI了。另外,插件系统也基本可用,后台使用JavaScript作为脚本语言,并使用rhino引擎解释。可以看一个例子:
/* * put all initialize code here */ function _init_(){ var app = application; var ui = app.getUI(); //set look and feel to windows ui.setLookAndFeel("windows"); //load some new scripts app.activePlugin("scripts/help.js"); app.activePlugin("scripts/util.js"); var menubar = ui.getMenuBar(); //menubar.add(new menu("", "", "")) //launch the main frame app.launch(); }
而同时在Java代码中,将application(STodo的实例)作为变量传递给脚本,就可以实现两者的通信了:
public static void main(String[] args){ STodo sTodo = new STodo(new MainFrame("My todo list")); sTodo.initEnv(); Plugin system = TodoPluginManager.getInstance().getPlugin("system"); system.putValueToContext("application", sTodo); system.execute("_init_", new Object()); }
比如,上边的JavaScript代码中的这一句:
ui.setLookAndFeel("windows");
表示,将界面风格设置为windows主题,而:
ui.setLookAndFeel("motif");
表示,将界面风格设置为motif主题,就是SUN的那个solaris系统的默认风格。两者的对比如下:
关于脚本化Java,还可以参考这篇文章,是我之前发表在IBM Developerworks上的: 使用 JavaScript 脚本化 Java 应用 其中使用的例子就是这个sTodo. 目标后边需要加入更多的内容,下面是一个列表:
如果你有更好的建议,无论是UI方面的还是程序设计方面的,欢迎讨论之至。
更新最近离职了,新的公司要到5月10号左右去报到,因此有大量的时间来做sTodo后边的完善工作,经过近一周的重构,现在的sTodo已经基本可用了。正如上文中的目标部分列出来的项目,现在已经完成的己有:
现在根据一些细节来说明本次的更新:
在Java代码中,Java唯一知道的是system.js这个脚本,system.js会加载其他的脚本,进行一些初始化,然后调用java端暴露出来的launch方法启动整个应用。
function main(){ var app = Application; var ui = app.getUI(); //set look and feel to windows ui.setLookAndFeel("windows"); //load some new scripts app.activePlugin("scripts/json.js"); app.activePlugin("scripts/date.js"); app.activePlugin("scripts/util.js"); app.activePlugin("scripts/menubar.js"); app.activePlugin("scripts/misc.js"); app.launch(); //loadTodosFromFile("todos.txt"); } Application对象就是整个sTodo的引用,activePlugin(filename)方法会加载其他脚本并执行,上边的代码中可以看到,加载的有数据交换必须的json.js,日期格式分析的data.js,以及一些工具的定义util.js,还有UI方面的menubar.js,最后是杂项misc.js。加载完成之后,调用Application的launch方法启动应用。
值得一提的是,之前使用jQuery的extend方法,觉得非常好,特别在处理配置的时候,然后直接从jQuery中抽取出该方法:
var jQuery = jQuery || {}; jQuery.extend = function() { // copy reference to target object var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options; // Handle a deep copy situation if ( typeof target === "boolean" ) { deep = target; target = arguments[1] || {}; // skip the boolean and the target i = 2; } // Handle case when target is a string or something (possible in deep copy) if ( typeof target !== "object" && !jQuery.isFunction(target) ) target = {}; // extend jQuery itself if only one argument is passed if ( length == i ) { target = this; --i; } for ( ; i < length; i++ ) // Only deal with non-null/undefined values if ( (options = arguments[ i ]) != null ) // Extend the base object for ( var name in options ) { var src = target[ name ], copy = options[ name ]; // Prevent never-ending loop if ( target === copy ) continue; // Recurse if we're merging object values if ( deep && copy && typeof copy === "object" && !copy.nodeType ) target[ name ] = jQuery.extend( deep, // Never move original objects, clone them src || ( copy.length != null ? [ ] : { } ) , copy ); // Don't bring in undefined values else if ( copy !== undefined ) target[ name ] = copy; } // Return the modified object return target; }; 并将其定义在util.js中,然后在函数中调用它:
function createNewTodo(def){ var item = { desc : "short description", type : "node", timeout : "now +5 min", period : "never", status : "new", note : "long message type here." }; item = jQuery.extend(item, def); return item; } 这样,我就可以很随意的定义新的todo了:
function insertNewTodo(def){ //the default new to-do template var item = createNewTodo(def); DataModel.addItem(JSON.stringify(item)); } insertNewTodo({desc : "Gonna to kill bill", timeout : "tomorrow 10 am" }); insertNewTodo({desc : "Relive bill killed", timeout : "5/1 9 pm" }); 因为jQuery的extend的特性:有就替换,没有的话,就加入,因此用来处理传入参数非常方便。当然,jQuery的extend不止是这些功效,它还有更强大的地方,如深度扩展,不过暂时不做讨论。上边的代码就可以向sTodo中插入两个新的todo了。发送邮件的代码跟创建新的todo非常类似,就不一一列举了,感兴趣的话可以到sTodo的网站上下载代码做测试,sTodo托管在Google code上:https://code.google.com/p/stodo/。
另一个比较有意思的地方是关于菜单的定义上,我们可以定义一个类,专门用于创建菜单,当然是用JavaScript那种方式:
var STodoMenuItem = function(text, icon, func){ this.menu = new JMenuItem(); this.menu.setText(text); if(icon){ this.menu.setIcon(new ImageIcon(icon)); } if(func){ this.click(func); } }; STodoMenuItem.prototype.click = function(func){ this.menu.addActionListener( new JavaAdapter( ActionListener, { actionPerformed : func } ) ); }; STodoMenuItem.prototype.getMenuObject = function(){ return this.menu; } 这样定义之后,使用的时候就与前端的JavaScript操作非常类似了:
var menu = new STodoMenuItem("test", "imgs/plugin.png"); menu.click(function(){ alert("tomorrow is another day"); }); menuHelp.add(menu.getMenuObject()); 比如,这个click方法,完全就是参照jQuery对象的那种写法,效果如下:
当然,这里的Alert并非DOM中的window的属性,而是重新定义的,使用Swing的弹出对话框实现的: //show the message as a message dialog function alert(message){ JOptionPane.showMessageDialog( null, message, "Alert", JOptionPane.INFORMATION_MESSAGE); }好了,这一篇就先说这么多,代码开发之余,写写文档也是不错的。如果有下一篇,就讲讲sTodo中的任务调度部分,这是整个sTodo的核心。
声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|||
返回顶楼 | |||
发表时间:2010-04-26
最后修改:2010-04-26
用javascript做脚本语言?有意思,研究下。
有没有办法直接在HTML页面里面利用 JavaScript与Java通信,比如说读写文件,邮件什么的。 |
|||
返回顶楼 | |||
发表时间:2010-04-30
greatghoul 写道 用javascript做脚本语言?有意思,研究下。
有没有办法直接在HTML页面里面利用 JavaScript与Java通信,比如说读写文件,邮件什么的。 曾经见过一篇文章,写的非常棒: http://www.ibm.com/developerworks/cn/web/wa-aj-javaee/ 不过主要是在Server端使用JavaScript,然后通过JSP来调用(用JDK6里的脚本库),那样就可以实现用JavaScript来读写文件/发邮件,不过脚本泡在Server上,而不是客户端。 |
|||
返回顶楼 | |||
发表时间:2010-04-30
greatghoul 写道 用javascript做脚本语言?有意思,研究下。
有没有办法直接在HTML页面里面利用 JavaScript与Java通信,比如说读写文件,邮件什么的。 直接用客户端的JavaScript来做IO之类的恐怕不行,因为有安全方面的考虑,不过可以使用如lambda兄提到的这种方式:在Server端运行JavaScript来做相同的事情,脚本语言的好处在于不用编译,动态性,开发效率高。 不过要说这两者通信来完成IO/mail的话,可以看看这个: http://directwebremoting.org/dwr/index.html 引用 DWR is a Java library that enables Java on the server and JavaScript in a browser to interact and call each other as simply as possible .
不过我没有尝试过这个框架,只是推荐,呵呵。 |
|||
返回顶楼 | |||
发表时间:2010-04-30
看了看lz的sTodo最新版本的代码,感觉挺好的,特别是将JavaScript嵌入到Java中,这种模式非常好。
|
|||
返回顶楼 | |||
发表时间:2010-04-30
λ-lambda 写道 看了看lz的sTodo最新版本的代码,感觉挺好的,特别是将JavaScript嵌入到Java中,这种模式非常好。
嗯,我也觉得这种模式很有搞头,现在手头上有个小项目,准备将Java的一些基本的东西包装成方便JavaScript调用的形式,使得用JavaScript充分利用Java的好处,进行更方便的应用程序开发。设想一下: import("scripts/io.js"); import("scripts/net.js"); function jsTest(){ var s = Bios.open("file.txt"); var buffer = null; buffer = s.readLine(); //do something with the line. s.close(); } 诸如此类的,那样的话,开发起来可以充分利用JS的一些特性,又可以借助Java中强大的类库支持,将会是一个很有意思的方向。 |
|||
返回顶楼 | |||
发表时间:2010-04-30
你的JavaScript内核系列写完了没有?怎么又开始捣鼓Swing了?呵呵。
|
|||
返回顶楼 | |||
发表时间:2010-04-30
childrentown 写道 你的JavaScript内核系列写完了没有?怎么又开始捣鼓Swing了?呵呵。
呵呵,怎么说呢,这两个是相辅相成的,而且这段时间我的时间比较多,正好完善一下sTodo,第一个介绍sTodo的帖子是09年9月的,已经拖了半年天气了。sTodo涉及到了JavaScript在Java平台中的应用,也算是《JavaScript内核》的一个实例,应该不冲突吧? |
|||
返回顶楼 | |||
发表时间:2010-05-27
这个To-do List想办法和Google的Calender实现链接就好了。
楼主可否尝试? |
|||
返回顶楼 | |||