Nodejs用于桌面开发
Nodejs用于桌面开发
node的定位是,server-side javascript。 <br/> <br/>但程序员最爱做的事,就是把一个东西用在不该用的地方。那么,可以把node用在桌面开发上吗?当然可以。 <br/> <br/><!–more–><span>把Javascript用在桌面开发上,早有先例,比如GTK+的gjs,还有Qt的QML(顺带一提,QML代表着桌面开发的另一个方向,a promising way),GNOME3中,也用javascript作为桌面插件的开发语言。</span> <br/> <br/>那么为何要多此一举,把node引入到桌面开发上? 因为node的网络编程能力。使用node,你可以十几分钟就写出一个微博客户端来,而且代码简单明了,这种内在的网络能力,是其他所有语言欠缺的。 <br/><h4>第一个例子</h4> <br/>那么,单刀直入,让我们先看一个hello world: <br/><pre>var gui = require(’…/lib/gui’); <br/> <br/>var window = new gui.Window ({ <br/> ‘title’: ‘node-gui’, <br/> ‘window-position’: 1, <br/> ‘opacity’: 0.5 <br/>}); <br/> <br/>window.show (); <br/> <br/>window.on (‘delete-event’, function () { <br/> gui.quit (); <br/>});</pre> <br/>代码很简单, 就像其他所有module一样。 <br/> <br/>首先,我们使用new Window建立了一个新窗口,参数是窗口property的列表,分别代表标题、位置、透明度,其它属性可以在<a href=“http://developer.gnome.org/gtk/2.24/GtkWindow.html” target="_blank">GTK+文档</a>里查到。 然后,我们调用了show方法。接着,使窗口响应’delete-event’消息,在窗口关闭时退出。 <br/><h4>node-gui</h4> <br/>代码中引用的module在这里: https://github.com/zcbenz/node-gui/ ,内有详细说明。 <br/> <br/>可以直接用npm安装:npm install gui <br/> <br/>编译时需要注意,你需要GTK+开发库支持。而且因为耍了很多C++11的花枪,你还需要很新的GCC4.6。 <br/> <br/>为node编写界面库的难点,在于把两种格格不入的事件循环融合起来。我采用的方案,是将GTK+主循环放在新线程中进行,一来简化了逻辑,二来GUI操作向来费时,把GUI操作放在新线程中操作符合异步的要义。 <br/><h4>Windows</h4> <br/>提到桌面开发,Windows从来是不得不支持的平台。node已经部分支持了Windows,那么使用node-gui的程序能在Windows下跑起来吗?可以,但是需要艰苦卓绝的努力。 <br/> <br/>node Windows porting尚未实现功能之一,就是native C++ module的支持(如果你想知道原因,是因为模板类成员函数无法导出到额外加载的DLL中),这几乎堵死了我的路。不过经过一番努力,我把node-gui作为node的一部分编译入了node,成功运转了起来。(另外,如果你想亲自尝试的话,为了获得更好的用户体验,最好在编译选项中把Console Window取消掉。) <br/> <br/>但是坦言说来,这样没有太大意义,Windows下的GTK+运行库大约有18mb,而且GTK+3也暂时没有Windows的二进制库(原来的贡献者退出了)。为几kb的脚本付出二十来mb的运行时代价,用户不会买账的(也是为何鲜有民用桌面软件采用.NET开发)。 <br/><h4>复杂的例子</h4> <br/>那么,让我们再接着看一个复杂些的例子,这次我们用上了网络: <br/><pre>var gui = require (’…/lib/gui’); <br/>var http = require (‘http’); <br/> <br/>new gui.Builder (__dirname + ‘/download.glade’, function (builder) { <br/> var window = builder.get (‘window’ , gui.Window ) ; <br/> var download = builder.get (‘download’ , gui.Button ) ; <br/> var url = builder.get (‘url’ , gui.Entry ) ; <br/> var text = builder.get (‘text’ , gui.TextView ) ; <br/> <br/> window.setBorderWidth (10); <br/> window.show (); <br/> <br/> window.on (‘delete-event’, function () { <br/> gui.quit (); <br/> process.exit (0); <br/> }); <br/> <br/> var onDownload = function () { <br/> var sUrl = url.getText (); <br/> <br/> var options = require (‘url’).parse (sUrl); <br/> var data = “”; <br/> var req = http.request (options, function (res) { <br/> res.on (‘data’, function (chunk) { <br/> var buffer = text.getBuffer (); <br/> var str = String (chunk); <br/> buffer.insertAtCursor (str, str.length); <br/> }); <br/> <br/> res.on (‘end’, function () { <br/> download.setLabel (‘Download’); <br/> download.setSensitive (true); <br/> }); <br/> }); <br/> <br/> req.on (‘error’, function (e) { <br/> var message = new gui.MessageDialog ({ <br/> ‘buttons’: 1, <br/> ‘text’: ‘Networking Error’, <br/> ‘secondary-text’: e.message <br/> }); <br/> message.show (); <br/> message.on (‘response’, function () { <br/> message.destroy (); <br/> }); <br/> <br/> download.setLabel (‘Download’); <br/> download.setSensitive (true); <br/> }); <br/> <br/> req.on (‘response’, function () { <br/> text.getBuffer ().setProperty (‘text’, ‘’); <br/> }); <br/> <br/> req.end (); <br/> <br/> download.setLabel (‘Downloading…’); <br/> download.setSensitive (false); <br/> }; <br/> <br/> download.on (‘clicked’, onDownload); <br/> url.on (‘activate’, onDownload); <br/>});</pre> <br/>代码我不再详述,<a href=“https://github.com/zcbenz/node-gui/”>github页面</a>有(不太)详细的文档。简单说来,Builder可以从XML文件里直接构造界面,而GUI事件循环也可以和node的网络事件完美融合起来。 <br/> <br/>界面截图: <br/> <br/><a href=“http://static.data.taobaocdn.com/up/nodeclub/2011/10/Screenshot.png”><img class=“alignnone size-medium wp-image-3585” src=“http://static.data.taobaocdn.com/up/nodeclub/2011/10/Screenshot-281x300.png” alt="" width=“281” height=“300” /></a> <br/><h4>未来</h4> <br/>这只是一个玩具,开发的唯一目的,就是试试一个idea是否能成(另一个目的是想骗一只阿里云手机来玩,<( ̄︶ ̄)>,可惜不能如愿)。所以,请不要把它用来生产项目中。 <br/> <br/>而且,因为对GTK+和C++11的依赖,大部分同学到这里,应该都还没编译成功吧…… ╮( ̄▽ ̄)╭ <br/> <br/>严肃地看来,作为真正的跨平台GUI库,Qt应该是个更好的选择。更严肃地看来,为每个平台单独开发界面库,更符合用户的需求。更更严肃地看来,拿C++写桌面程序,用户才会买账。那都是后话了。
Node.js 用于桌面开发
Node.js 最初的定位是服务器端 JavaScript,但它强大的网络编程能力和异步处理机制使其在桌面应用开发中也有着广泛的应用前景。
为什么使用 Node.js 进行桌面开发?
Node.js 的网络编程能力使得开发者可以轻松地构建出功能强大的桌面应用程序。例如,你可以在十几分钟内编写一个简单的微博客户端,代码简洁且易于维护。
示例代码
第一个例子:Hello World
var gui = require('nw.gui'); // 引入 nw.gui 模块
// 创建一个新的窗口实例,并设置其属性
var win = new gui.Window({
'width': 800,
'height': 600,
'title': 'Node.js Desktop App',
'toolbar': false
});
// 显示窗口
win.show();
// 当窗口关闭时触发的事件
win.on('close', function() {
win.close(true); // 关闭窗口
});
这段代码展示了如何使用 Node.js 和 nw.gui
模块创建一个简单的桌面应用窗口。通过设置窗口的宽度、高度、标题等属性,我们可以定制窗口的行为。
复杂一些的例子:下载器
var gui = require('nw.gui');
var http = require('http');
// 使用 Builder 从 XML 文件中构建界面
new gui.Builder(__dirname + '/download.glade', function(builder) {
var window = builder.get('window', gui.Window);
var downloadBtn = builder.get('download', gui.Button);
var urlEntry = builder.get('url', gui.Entry);
var textArea = builder.get('text', gui.TextView);
window.show();
window.on('close', function() {
gui.App.quit(); // 关闭应用
});
// 下载按钮点击事件处理
downloadBtn.on('click', function() {
var url = urlEntry.text;
var options = require('url').parse(url);
var req = http.request(options, function(res) {
res.on('data', function(chunk) {
textArea.appendText(chunk.toString());
});
res.on('end', function() {
downloadBtn.label = 'Download';
downloadBtn.enabled = true;
});
});
req.on('error', function(e) {
var msgDialog = new gui.MessageDialog({
'type': 'info',
'buttons': ['OK'],
'title': 'Error',
'text': 'Networking Error',
'detail': e.message
});
msgDialog.show();
});
req.end();
downloadBtn.label = 'Downloading...';
downloadBtn.enabled = false;
});
// URL 输入框激活事件处理
urlEntry.on('activate', function() {
downloadBtn.click();
});
});
这段代码展示了一个更复杂的例子,其中包含了一个简单的下载器。它从指定的 URL 获取数据,并将其显示在一个文本区域中。当用户点击“下载”按钮或按回车键时,会触发下载操作。
结论
虽然 Node.js 可以用于桌面开发,但由于其对 GTK+ 和 C++11 的依赖,编译过程可能会比较复杂。对于跨平台的桌面应用开发,使用 Qt 或其他专门针对桌面开发的框架可能是更好的选择。不过,Node.js 仍然是一个值得探索的工具,特别是在那些需要强大网络功能的应用场景中。
新手, Ubuntu 11.10 自带的 nodejs, 安装的 npm, <br/>有些包安装正常, 有的不正常, search 命令没反应, <br/>然后请问这个…: <br/>$ sudo npm install -g gui <br/>npm ERR! Error: Not found: gui@’’ <br/>npm ERR! Valid install targets: <br/>npm ERR! [“latest”] <br/>npm ERR! at installTargetsError (/usr/lib/node_modules/npm/lib/cache.js:410:10) <br/>npm ERR! at /usr/lib/node_modules/npm/lib/cache.js:403:17 <br/>npm ERR! at saved (/usr/lib/node_modules/npm/lib/utils/npm-registry-client/get.js:136:7) <br/>npm ERR! at cb (/usr/lib/node_modules/npm/node_modules/graceful-fs/graceful-fs.js:36:9) <br/>npm ERR! Report this entire log at: <br/>npm ERR! <br/>npm ERR! or email it to: <br/>npm ERR! <br/>npm ERR! <br/>npm ERR! System Linux 3.0.0-12-generic <br/>npm ERR! command “node” “/usr/bin/npm” “install” “-g” “gui” <br/>npm ERR! cwd /home/chen/code/nodejs <br/>npm ERR! node -v v0.4.9 <br/>npm ERR! npm -v 1.0.99 <br/>npm ERR! <br/>npm ERR! Additional logging details can be found in: <br/>npm ERR! /home/che/npm-debug.log <br/>npm not ok
gui 这个库是需要node v0.5.8 以上版本 <br/>0.4 是不行的 <br/> <br/>linux下编译没问题 <br/>windows下就不尝试了 <br/>反正以后作者会直接放出exe文件
[@Onolake](/user/Onolake) , 看到版本的问题了, 尝试去升级 5.10 , 过程在这里…
<br/>http://hi.baidu.com/jiyinyiyong/blog/item/0f0627d584d25acf562c847b.html
<br/>但还是有报错, 请问有什么原因吗?
<br/>sudo npm install -g gui
<br/>[sudo] password for c:
<br/>npm WARN gui@0.0.1 package.json: bugs[‘web’] should probably be bugs[‘url’]
<br/>
<br/>> gui@0.0.1 preinstall /usr/local/lib/node_modules/gui
<br/>> node-waf configure
<br/>
<br/>Setting srcdir to : /usr/local/lib/node_modules/gui
<br/>Setting blddir to : /usr/local/lib/node_modules/gui/build
<br/>Checking for program g++ or c++ : /usr/bin/g++
<br/>Checking for program cpp : /usr/bin/cpp
<br/>Checking for program ar : /usr/bin/ar
<br/>Checking for program ranlib : /usr/bin/ranlib
<br/>Checking for g++ : ok
<br/>Checking for node path : ok /home/c/.node_libraries
<br/>Checking for node prefix : ok /usr/local
<br/>Checking for pkg-config version >= 0.0.0 : yes
<br/>Checking for gtk±2.0 : not found
<br/>‘configure’ finished successfully (0.922s)
<br/>
<br/>> gui@0.0.1 install /usr/local/lib/node_modules/gui
<br/>> node-waf build install
<br/>
<br/>Waf: Entering directory /usr/local/lib/node_modules/gui/build'
<br/>[ 1/34] cxx: src/main.cc -> build/Release/src/main_1.o
<br/>[ 2/34] cxx: src/node_gui_misc.cc -> build/Release/src/node_gui_misc_1.o
<br/>[ 3/34] cxx: src/impl_mainloop_gtk.cc -> build/Release/src/impl_mainloop_gtk_1.o
<br/>[ 4/34] cxx: src/node_gui_global.cc -> 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’
<br/>Build failed:
<br/> -> task failed (err #1):
<br/> {task: cxx impl_mainloop_gtk.cc -> impl_mainloop_gtk_1.o}
<br/> -> task failed (err #1):
<br/> {task: cxx node_gui_global.cc -> node_gui_global_1.o}
<br/> -> task failed (err #1):
<br/> {task: cxx node_gui_misc.cc -> node_gui_misc_1.o}
<br/>npm ERR! error installing gui@0.0.1 Error: gui@0.0.1 install: node-waf build install
<br/>npm ERR! error installing gui@0.0.1 sh "-c" "node-waf build install"
failed with 1
<br/>npm ERR! error installing gui@0.0.1 at ChildProcess. (/usr/local/lib/node_modules/npm/lib/utils/exec.js:49:20)
<br/>npm ERR! error installing gui@0.0.1 at ChildProcess.emit (events.js:70:17)
<br/>npm ERR! error installing gui@0.0.1 at maybeExit (child_process.js:336:16)
<br/>npm ERR! error installing gui@0.0.1 at Process.onexit (child_process.js:371:5)
<br/>npm ERR! gui@0.0.1 install: node-waf build install
<br/>npm ERR! sh "-c" "node-waf build install"
failed with 1
<br/>npm ERR!
<br/>npm ERR! Failed at the gui@0.0.1 install script.
<br/>npm ERR! This is most likely a problem with the gui package,
<br/>npm ERR! not with npm itself.
<br/>npm ERR! Tell the author that this fails on your system:
<br/>npm ERR! node-waf build install
<br/>npm ERR! You can get their info via:
<br/>npm ERR! npm owner ls gui
<br/>npm ERR! There is likely additional logging output above.
<br/>npm ERR!
<br/>npm ERR! System Linux 3.0.0-12-generic
<br/>npm ERR! command “node” “/usr/local/bin/npm” “install” “-g” “gui”
<br/>npm ERR! cwd /home/c/Downloads
<br/>npm ERR! node -v v0.5.10
<br/>npm ERR! npm -v 1.0.103
<br/>npm ERR! code ELIFECYCLE
<br/>npm ERR!
<br/>npm ERR! Additional logging details can be found in:
<br/>npm ERR! /home/c/Downloads/npm-debug.log
<br/>npm not ok
按照 Github 的安装过程, 有个 libgtk2.0-dev , 装上之后 gui 安装成功, <br/>$ node g.js # 抱歉继续带来新手问题… 复制上方代码, 修改 require(‘gui’), <br/># 而且在 node shell 里面测试 require(‘gui’) 成功的, 可是: <br/>g.js:215: Uncaught Error: Widget does not exsit
其实为什么不使用html作为gui呢?node有很好的websocket支持,html具有极佳 <br/>的表现能力.对于gui的数据交换,使用websocket也足够.不过是在本地多开一个端 <br/>口而已呢.
目前基于Qt的Node-qt和Node-five支持Windows平台 https://github.com/arturadib/node-qt https://github.com/arturadib/node-five
mark
Node.js 通常被用于服务器端的 JavaScript 开发,但通过一些扩展库,它也可以用于桌面应用开发。这可以利用 Node.js 在网络编程和事件驱动方面的优势。例如,node-gui
是一个基于 Node.js 的库,允许开发者创建桌面应用。
示例代码
这里有一个简单的例子,展示如何使用 node-gui
创建一个具有基本功能的桌面应用:
var gui = require('node-gui');
var http = require('http');
new gui.Builder(__dirname + '/interface.glade', function(builder) {
var window = builder.get('mainWindow', gui.Window);
var button = builder.get('downloadButton', gui.Button);
var urlEntry = builder.get('urlEntry', gui.Entry);
var textView = builder.get('textView', gui.TextView);
window.show();
window.on('delete-event', function() {
gui.quit();
process.exit(0);
});
var downloadFile = function() {
var url = urlEntry.getText();
var options = require('url').parse(url);
var data = "";
var request = http.request(options, function(response) {
response.on('data', function(chunk) {
var buffer = textView.getBuffer();
buffer.insertAtCursor(String(chunk), String(chunk).length);
});
response.on('end', function() {
button.setLabel('Download');
button.setSensitive(true);
});
});
request.on('error', function(error) {
var dialog = new gui.MessageDialog({
'buttons': 1,
'text': 'Networking Error',
'secondary-text': error.message
});
dialog.show();
dialog.on('response', function() {
dialog.destroy();
});
button.setLabel('Download');
button.setSensitive(true);
});
request.end();
button.setLabel('Downloading...');
button.setSensitive(false);
};
button.on('clicked', downloadFile);
});
解释
- 导入模块:首先导入
node-gui
和http
模块。 - 构建界面:使用
gui.Builder
从 GLADE 文件加载并初始化界面元素。 - 显示窗口:调用
window.show()
显示窗口。 - 事件处理:监听窗口关闭事件,并在关闭时退出应用。
- 下载功能:当按钮被点击时,触发下载功能。该功能包括发起 HTTP 请求,接收数据并在文本视图中显示数据。
这个例子展示了如何结合使用 Node.js 的网络能力和 node-gui
库来创建一个简单的桌面应用。这样的组合提供了强大的灵活性和便捷性。