用node作桌面开发
发布于 3年前 作者 fool 7253 次浏览

node的定位是,server-side javascript。

但程序员最爱做的事,就是把一个东西用在不该用的地方。那么,可以把node用在桌面开发上吗?当然可以。

把Javascript用在桌面开发上,早有先例,比如GTK+的gjs,还有Qt的QML(顺带一提,QML代表着桌面开发的另一个方向,a promising way),GNOME3中,也用javascript作为桌面插件的开发语言。

那么为何要多此一举,把node引入到桌面开发上? 因为node的网络编程能力。使用node,你可以十几分钟就写出一个微博客户端来,而且代码简单明了,这种内在的网络能力,是其他所有语言欠缺的。

第一个例子


那么,单刀直入,让我们先看一个hello world:
var gui = require(‘…/lib/gui’);


var window = new gui.Window ({
'title’: 'node-gui’,
'window-position’: 1,
'opacity’: 0.5
});

window.show ();

window.on ('delete-event’, function () {
gui.quit ();
});

代码很简单, 就像其他所有module一样。

首先,我们使用new Window建立了一个新窗口,参数是窗口property的列表,分别代表标题、位置、透明度,其它属性可以在GTK+文档里查到。 然后,我们调用了show方法。接着,使窗口响应’delete-event’消息,在窗口关闭时退出。

node-gui


代码中引用的module在这里: https://github.com/zcbenz/node-gui/ ,内有详细说明。

可以直接用npm安装:npm install gui

编译时需要注意,你需要GTK+开发库支持。而且因为耍了很多C++11的花枪,你还需要很新的GCC4.6。

为node编写界面库的难点,在于把两种格格不入的事件循环融合起来。我采用的方案,是将GTK+主循环放在新线程中进行,一来简化了逻辑,二来GUI操作向来费时,把GUI操作放在新线程中操作符合异步的要义。

Windows


提到桌面开发,Windows从来是不得不支持的平台。node已经部分支持了Windows,那么使用node-gui的程序能在Windows下跑起来吗?可以,但是需要艰苦卓绝的努力。

node Windows porting尚未实现功能之一,就是native C++ module的支持(如果你想知道原因,是因为模板类成员函数无法导出到额外加载的DLL中),这几乎堵死了我的路。不过经过一番努力,我把node-gui作为node的一部分编译入了node,成功运转了起来。(另外,如果你想亲自尝试的话,为了获得更好的用户体验,最好在编译选项中把Console Window取消掉。)

但是坦言说来,这样没有太大意义,Windows下的GTK+运行库大约有18mb,而且GTK+3也暂时没有Windows的二进制库(原来的贡献者退出了)。为几kb的脚本付出二十来mb的运行时代价,用户不会买账的(也是为何鲜有民用桌面软件采用.NET开发)。

复杂的例子


那么,让我们再接着看一个复杂些的例子,这次我们用上了网络:
var gui = require (‘…/lib/gui’);

var http = require (‘http’);

new gui.Builder (__dirname + '/download.glade’, function (builder) {
var window = builder.get (‘window’ , gui.Window ) ;
var download = builder.get (‘download’ , gui.Button ) ;
var url = builder.get (‘url’ , gui.Entry ) ;
var text = builder.get (‘text’ , gui.TextView ) ;

window.setBorderWidth (10);
window.show ();

window.on ('delete-event’, function () {
gui.quit ();
process.exit (0);
});

var onDownload = function () {
var sUrl = url.getText ();

var options = require (‘url’).parse (sUrl);
var data = "";
var req = http.request (options, function (res) {
res.on ('data’, function (chunk) {
var buffer = text.getBuffer ();
var str = String (chunk);
buffer.insertAtCursor (str, str.length);
});

res.on ('end’, function () {
download.setLabel (‘Download’);
download.setSensitive (true);
});
});

req.on ('error’, function (e) {
var message = new gui.MessageDialog ({
'buttons’: 1,
'text’: 'Networking Error’,
'secondary-text’: e.message
});
message.show ();
message.on ('response’, function () {
message.destroy ();
});

download.setLabel (‘Download’);
download.setSensitive (true);
});

req.on ('response’, function () {
text.getBuffer ().setProperty ('text’, ‘’);
});

req.end ();

download.setLabel (‘Downloading…’);
download.setSensitive (false);
};

download.on ('clicked’, onDownload);
url.on ('activate’, onDownload);
});

代码我不再详述,github页面有(不太)详细的文档。简单说来,Builder可以从XML文件里直接构造界面,而GUI事件循环也可以和node的网络事件完美融合起来。

界面截图:


未来


这只是一个玩具,开发的唯一目的,就是试试一个idea是否能成(另一个目的是想骗一只阿里云手机来玩,<( ̄︶ ̄)>,可惜不能如愿)。所以,请不要把它用来生产项目中。

而且,因为对GTK+和C++11的依赖,大部分同学到这里,应该都还没编译成功吧…… ╮( ̄▽ ̄)╭

严肃地看来,作为真正的跨平台GUI库,Qt应该是个更好的选择。更严肃地看来,为每个平台单独开发界面库,更符合用户的需求。更更严肃地看来,拿C++写桌面程序,用户才会买账。那都是后话了。

16 回复

新手, Ubuntu 11.10 自带的 nodejs, 安装的 npm,
有些包安装正常, 有的不正常, search 命令没反应,
然后请问这个…:
$ sudo npm install -g gui
npm ERR! Error: Not found: [email protected]’’
npm ERR! Valid install targets:
npm ERR! [“latest”]
npm ERR! at installTargetsError (/usr/lib/node_modules/npm/lib/cache.js:410:10)
npm ERR! at /usr/lib/node_modules/npm/lib/cache.js:403:17
npm ERR! at saved (/usr/lib/node_modules/npm/lib/utils/npm-registry-client/get.js:136:7)
npm ERR! at cb (/usr/lib/node_modules/npm/node_modules/graceful-fs/graceful-fs.js:36:9)
npm ERR! Report this entire log at:
npm ERR!
npm ERR! or email it to:
npm ERR!
npm ERR!
npm ERR! System Linux 3.0.0-12-generic
npm ERR! command “node” “/usr/bin/npm” “install” "-g" “gui”
npm ERR! cwd /home/chen/code/nodejs
npm ERR! node -v v0.4.9
npm ERR! npm -v 1.0.99
npm ERR!
npm ERR! Additional logging details can be found in:
npm ERR! /home/che/npm-debug.log
npm not ok

gui 这个库是需要node v0.5.8 以上版本
0.4 是不行的

linux下编译没问题
windows下就不尝试了
反正以后作者会直接放出exe文件

@Onolake , 看到版本的问题了, 尝试去升级 5.10 , 过程在这里…
http://hi.baidu.com/jiyinyiyong/blog/item/0f0627d584d25acf562c847b.html
但还是有报错, 请问有什么原因吗?
sudo npm install -g gui
[sudo] password for c:
npm WARN [email protected] package.json: bugs[‘web’] should probably be bugs[‘url’]

> [email protected] preinstall /usr/local/lib/node_modules/gui
> node-waf configure

Setting srcdir to : /usr/local/lib/node_modules/gui
Setting blddir to : /usr/local/lib/node_modules/gui/build
Checking for program g++ or c++ : /usr/bin/g++
Checking for program cpp : /usr/bin/cpp
Checking for program ar : /usr/bin/ar
Checking for program ranlib : /usr/bin/ranlib
Checking for g++ : ok
Checking for node path : ok /home/c/.node_libraries
Checking for node prefix : ok /usr/local
Checking for pkg-config version >= 0.0.0 : yes
Checking for gtk±2.0 : not found
‘configure’ finished successfully (0.922s)

> [email protected] install /usr/local/lib/node_modules/gui
> node-waf build install

Waf: Entering directory /usr/local/lib/node_modules/gui/build' <br/>[ 1/34] cxx: src/main.cc -&gt; build/Release/src/main_1.o <br/>[ 2/34] cxx: src/node_gui_misc.cc -&gt; build/Release/src/node_gui_misc_1.o <br/>[ 3/34] cxx: src/impl_mainloop_gtk.cc -&gt; build/Release/src/impl_mainloop_gtk_1.o <br/>[ 4/34] cxx: src/node_gui_global.cc -&gt; build/Release/src/node_gui_global_1.o <br/>../src/node_gui_global.cc:1:21: fatal error: gtk/gtk.h: No such file or directory../src/impl_mainloop_gtk.cc:1:21: fatal error: gtk/gtk.h: No such file or directory <br/> <br/>compilation terminated. <br/>compilation terminated. <br/>In file included from ../src/node_gui_widget.h:4:0, <br/> from ../src/node_gui_misc.h:4, <br/> from ../src/node_gui_misc.cc:1: <br/>../src/node_gui_object.h:7:21: fatal error: gtk/gtk.h: No such file or directory <br/>compilation terminated. <br/>Waf: Leaving directory/usr/local/lib/node_modules/gui/build’
Build failed:
-> task failed (err #1):
{task: cxx impl_mainloop_gtk.cc -> impl_mainloop_gtk_1.o}
-> task failed (err #1):
{task: cxx node_gui_global.cc -> node_gui_global_1.o}
-> task failed (err #1):
{task: cxx node_gui_misc.cc -> node_gui_misc_1.o}
npm ERR! error installing [email protected] Error: [email protected] install: node-waf build install
npm ERR! error installing [email protected] sh "-c" "node-waf build install" failed with 1
npm ERR! error installing [email protected] at ChildProcess. (/usr/local/lib/node_modules/npm/lib/utils/exec.js:49:20)
npm ERR! error installing [email protected] at ChildProcess.emit (events.js:70:17)
npm ERR! error installing [email protected] at maybeExit (child_process.js:336:16)
npm ERR! error installing [email protected] at Process.onexit (child_process.js:371:5)
npm ERR! [email protected] install: node-waf build install
npm ERR! sh "-c" "node-waf build install" failed with 1
npm ERR!
npm ERR! Failed at the [email protected] install script.
npm ERR! This is most likely a problem with the gui package,
npm ERR! not with npm itself.
npm ERR! Tell the author that this fails on your system:
npm ERR! node-waf build install
npm ERR! You can get their info via:
npm ERR! npm owner ls gui
npm ERR! There is likely additional logging output above.
npm ERR!
npm ERR! System Linux 3.0.0-12-generic
npm ERR! command “node” “/usr/local/bin/npm” “install” "-g" “gui”
npm ERR! cwd /home/c/Downloads
npm ERR! node -v v0.5.10
npm ERR! npm -v 1.0.103
npm ERR! code ELIFECYCLE
npm ERR!
npm ERR! Additional logging details can be found in:
npm ERR! /home/c/Downloads/npm-debug.log
npm not ok

确实没编译通过,之前在node邮件组看到node-gui时就去下载了一个尝试。

按照 Github 的安装过程, 有个 libgtk2.0-dev , 装上之后 gui 安装成功,
$ node g.js # 抱歉继续带来新手问题… 复制上方代码, 修改 require(‘gui’),
# 而且在 node shell 里面测试 require(‘gui’) 成功的, 可是:
g.js:215: Uncaught Error: Widget does not exsit

其实为什么不使用html作为gui呢?node有很好的websocket支持,html具有极佳
的表现能力.对于gui的数据交换,使用websocket也足够.不过是在本地多开一个端
口而已呢.

@jiyinyiyong 为何用gtk,而不用QT呢?

@kingapple 我不会 C/C++ , 你问的这个我不知道

@jiyinyiyong 那你怎么知道st开发用的gtk呢?

@chrisak 在本地使用winsock做啥?IPC么?

@pl9165 这俩货被用于商业产品了么?

@kingapple 忘了… st 是什么东西, 不要用别人看不懂的缩写好吧

@jiyinyiyong 。。。 应该是看到过,不过刚才在帖子里搜了下,没看到了。。。

回到顶部