2010年7月21日星期三

Web界面的桌面应用程序

标题起空泛了,而且还跑题。。。

qooxdoo

qooxdoo是一个开源AjaxWeb应用程序框架。

其官方说明是
qooxdoo is a comprehensive and innovative framework for creating rich internet applications (RIAs). Leveraging object-oriented JavaScript allows developers to build impressive cross-browser applications. No HTML, CSS nor DOM knowledge is needed.

以个人的熟悉的话,会拿qooxdoo和qt做类比(其实是像Java库)。同样是应用程序框架,不过运行的环境并不相同。
话说qooxdoo可作为swt的前端,那么类比而言做Qt的前端的也是可以的。只不过显示交给了浏览器,而一些功能实现要由Ajax交给服务端(Qt有Network模块)来处理。
说浏览器中的库的话,自然会想到jQuery。而如果仅在Web中呈现GUI的话,jquery-easyui那样从内容展示出发的模块显然会更好用一点。
这么来说2005年便成立项目的qooxdoo,其本意浏览器中实现供JavaScript使用的应用程序开发框架了。


Hello World

使用create-application.py生成一个项目目录,例如
create-application.py --name=demo

在生成的目录中,/source/class/demo/Application.js便是需要编辑的文件。
此外有一个generate.py文件,需要先执行
./generate.py source-all
把全部的Class都导入,这样编写时就可以不必再用它来分析代码的依赖。
之后
./generate.py build
生成发布用的代码,就已经有近500k之巨了。

这里的Application.js已经包含最基本的模板,其中涉及qx的对象机制以及GUI工具箱的使用。
看起来有Java代码的感觉,在sdk中demobrowser有示例代码,playground里可以立即执行代码,"generate.py api"用以为当前项目生成文档,Manual则是首先必须了解到的。

此外,qx提供了Debug和Unit Testing的支持,以及一个Inspector。


Remote Procedure Call

基本的Ajax的话是使用qx.io.remote.Request,高层一点的qx.data.store.Json用于读取json,然后是基于JSON-RPC的qx.io.remote.Rpc。
它们都是按照先创建实例然后设置属性在调用的方式使用。
Rpc提供callSync和callAsync远程调用服务端提供的函数。
对服务端的语言没有限制,调用时需要对数据类型进行转换。

qx第三方提供的RPC_Python模块提供的接口看起还是挺优雅的,也实现了简单session机制。
作为实现的参考还是不错的,可以年久并不能实际使用。
这么来看在RPC方面还是需要来自己实现一点东西,不过这反而可以去使用一些已经熟悉的网络框架吧。
Python自带的话,有个xmlrpc模块。一般的话选个Web开发框架就可以了。

还有一个类似GWT的东西,由Java代码生成qx代码。


Web Interface

一些下载软件有提供本机或远程在浏览器中使用的Web界面。
例如emule,mldonkey,它们将自身作为一个Web服务器。
同过URI或者Form来以GET或POST的方式,使用HTTP协议(CURL也可用)。

如果单纯说HTTP的话,就可以是一个RESTFUL的API了。
不过对于以上所列的两款软件来说,并没有使用Ajax的方式。
只是单纯的信息的展示与提交,不过对这样的应用来说也足够了。

在Python中,webbrowser.open_new(url)会在浏览器中打开地址。
服务端的话派生BaseHTTPRequestHandler并实现do_GET和do_POST方法。
通过wfile回数据时先发head,就像SimpleHTTPRequestHandler实现的那样,
在Py的安装目录下可以看到代码。

不过这显然是以上若干节所说的有区别的,这里偏向于API。
而之前在说的是rich internet applications (RIAs),算Web application的范畴。


pyjs

一个Python Javascript Compiler,由Python代码编译出javascript代码。
属于Pyjamas项目,是一个GWT的Python实现,还包含AJAX framework和Widget Set API。
pyjs包括两部分,一是通过Py的语法树生成js代码,另一个则是用js实现了py的基本对象类型。
有个Pyjamas Desktop子版本用于类似Air的桌面程序。
暂且提及一下,略过。


Code Examples

最后堆点不完整的复制来的代码供参考,来源是各自官方。


qx.helloworld.js
qx.Class.define("demo.Application",
{
extend : qx.application.Standalone,
members :
{
main : function()
{
this.base(arguments);
var button1 = new qx.ui.form.Button("First Button");
var doc = this.getRoot();
doc.add(button1, {left: 100, top: 50});
button1.addListener("execute", function(e) {
alert("Hello World!");
});
}
}
});
或创建窗口:
 var win = new qx.ui.window.Window(
"First Window");

win.setPadding(10);
win.setLayout(new qx.ui.layout.VBox(10));
win.add(new qx.ui.form.Button("Hello World"));

win.open();
继承层次结构是
Object>qx.core.Object>qx.ui.core.LayoutItem>qx.ui.core.Widget>qx.ui.window.Window


qx.io.remote.Rpc
var rpc = new qx.io.remote.Rpc(
"http://localhost:8080/qooxdoo/.qxrpc",
"qooxdoo.test"
);

// synchronous call
try {
var result = rpc.callSync("echo", "Test");
alert("Result of sync call: " + result);
} catch (exc) {
alert("Exception during sync call: " + exc);
}

// asynchronous call
var handler = function(result, exc) {
if (exc == null) {
alert("Result of async call: " + result);
} else {
alert("Exception during async call: " + exc);
}
};
rpc.callAsync(handler, "echo", "Test");

//Aborting a call
//var callref = rpc.callAsync(handler, "echo", "Test");
//rpc.abort(callref);
RPC对象,以及两种调用方法。


RPC with a Python server
#!/usr/bin/python
# -*- coding: ascii -*-

import qxjsonrpc
import qxjsonrpc.http

class ExampleWikiService(object):
def __init__(self):
self.total=0
@qxjsonrpc.public
def add(self, *args):
for value in args:
self.total+=value
return self.total

def main():
server=qxjsonrpc.http.HTTPServer()
server.setService('example.wiki', ExampleWikiService())
server.serve_forever()

if __name__=='__main__': main()
加@qxjsonrpc.session话会传入一个session参数。


Python.BaseHTTPServer
def run(server_class=BaseHTTPServer.HTTPServer,
handler_class=BaseHTTPServer.BaseHTTPRequestHandler):
server_address = ('', 8000)
httpd = server_class(server_address, handler_class)
while True:
httpd.handle_request()
这里需要实现自己的handler_class子类,while语句后面可控制是否退出。


...

标题就是,写了个本地应用,然后拿浏览器渲染界面的意思。。。

没有评论: