书摘和访谈:《FXRuby:用 Ruby 创建精简的 GUI》

阅读数:1398 2008 年 5 月 27 日

话题:Ruby语言 & 开发

Lyle Johnson 的《FXRuby:用 Ruby 创建精简的 GUI》是一本关于FXRuby的新书。FXRuby 是基于FOX 工具包的一个 Ruby GUI 库。

出版商The Pragmatic Programmers专门为 InfoQ 的读者提供了独家的样章:“第 8 章:创建简单的小部件(Widgets)”(PDF)。

我们访问了该书的作者和 FXRuby 的维护者Lyle Johnson谈一谈FOX 工具包和 FXRuby 的设计和实现

InfoQ: FXRuby 是基于 FOX 工具包的。请你简要概括一下它的特点——例如对比本地小部件和仿真的小部件(widgets),以及支持的平台等。它有哪些特性、概念和优势,可以从众多的 GUI 工具包中脱颖而出?

Lyle Johnson: FOX 是一个用 C++ 实现的快速且轻量级的 GUI 工具包。它是跨平台的,不仅能很好地支持流行的操作系统(比如 Windows、Mac OS X 和 Linux),也支持其他很多不常见的类 Unix 操作系统。FOX 使用轻量级的(非本地的)小部件,也就是说 FOX 只依赖宿主平台的基本绘图能力,而 不是对已有的(本地的)小部件进行包装。这种方法有很多优势,包括跨平台的一致性和更强的扩展性。

FOX 提供了创新的、独一无二的解决方案来进行事件处理和布局。我觉得这就是它和其它 GUI 工具包之间最大的区别。FOX 的 开发者花了大量的时间来使用许多不同种类的 GUI 工具包,从中获取经验,最终创建了 FOX。对他影响最深的是 NeXT,还有用很多方法实现的 API。在高 一点的层次上,FOX 对 3-D 可视化(使用 OpenGL)的支持特别好,这也吸引了很多人来使用 FOX。

InfoQ: FOX 工具包的背后都有谁——有哪些知名的应用程序是基于它的(不局限于 Ruby 应用程序)?

Lyle Johnson: FOX 的开发者是 Jeroen van der Zijp。他是我的老朋友,以前跟我合作过。我们曾经同在一家开发工程用的商业建模、仿真和分析软件的公司里工作,那时候 Jeroen 就开始开发 FOX 了。鉴于它的起源,FOX 常被用在那个领域的商业和开源软件中。举例来说,商业公司如ESI GroupSimuliaCAE都在他们的 3-D 建模和可视化产品中使用 FOX。但是,我们也看到 FOX 和 FXRuby 用在许多其他领域的应用中,包括开发工具如FreeRIDEArachno Ruby IDE;视听工具如ReZoundGoggles DVD 播放器;谁知道还有多少,很难去追踪。

InfoQ: FXRuby 项目的背后有什么故事呢?你开发它的动机是什么?

Lyle Johnson: 我在 2000 年开始接触 Ruby,那时还没有很多成熟的、支持良好的跨平台 Ruby GUI 工具包。我对 FOX 以及开发 FOX 用的 Python 绑定已经有了不少经验,因此我很自然地想要把 FOX 带入 Ruby 社区。我在最近的“工作”中无法 使用 FOX,但我知道 Ruby 社区中有很多人都觉得它很有用,这驱使着我对它继续开发和完善。

InfoQ: FXRuby 是如何实现的——用了多少 C 或者 C++ 代码?你是怎样把 FOX 组件映射到 Ruby 架构中的?FXRuby 能够随意使用 FOX 组件吗?还是你需要用 C/C++ 来把它们映射到 Ruby 中?你用什么来把 Ruby 连接到 FOX 上——用一般的 C 扩展还是 C++ 绑定?

Lyle Johnson: 我用了很多 C++ 代码,但大部分的包装(wrapper)代码是用SWIG自 动产生的,由此实现了 FOX 和 Ruby 的绑定。FXRuby 现在还不能动态地、即插即用地使用所有的 FOX 组件;你需要用 SWIG 来包装它们,并且遵循我 在 FXRuby 内部使用的一些约定,比如怎样与 Ruby 的垃圾收集器进行交互。实际上,FXRuby 的一小部分(并且会越来越多)是用 Ruby 实现的。但 是,我喜欢向更有意义且不会严重影响性能的方向努力。



InfoQ: FOX 工具包好像还包括了许多工具(定时器、异步 I/O 等)。FXRuby 支持这些吗?如果现在不支持,你想要支持哪些?

Lyle Johnson: 我正在实现 FOX 所有的“功能”,只要它们是有用的,比如杂事处理、超时事件、异步 I/O 事件,还有像注册(registry)这样的服务。FOX 还提供 了其它许多有用的类,比如收集器、线程和正则表达式,但都是多余的,因为 Ruby 标准库中已经提供了这些类。因此我没有把它们放进 FXRuby。



InfoQ: FXRuby 的 Ruby 化进行得怎样?比如,它是否支持 Ruby 块(事件处理等)?能不能使用Builder风格的 GUI 定义?

Lyle Johnson: 我下了很大功夫让 API 更加“Ruby 化”。你可以传递块来作为事件处理器,而不需要单独写实例方法并和小部件(widgets)绑在一起。还有在其他许 多地方,只要你觉得应该使用块,我们都尽量用了。举例来说,当你处理一个对象集合(比如列表部件里的项目)时,你可以把一个块传递给该部件的each方法。



由 于一个部件构造器可以接收一个块,并作为引用传递给正要构造的部件上,因此在某种程度上,你可以用嵌套的风格来构造 GUI。换句话说,这些部件的变量可以 既不污染本地的命名空间,也不会破坏反映部件从属关系的嵌套代码。还有,FXRuby 不是一个 DSL 类的 Builder;你仍需要明确地构造每一个对象。

InfoQ: FXRuby 和它的事件处理机制是怎样与 Ruby 1.8.x 的线程机制进行互动的?比如说,如果一个 Ruby 线程遇到一个正在阻塞的、需要长时间运行的系统调用——那么 FXRuby GUI 也会被阻塞吗?从另外一个角度说:FXRuby 的事件队列是如何实现的?如果没有 GUI 事件进入 FXRuby 队列——其他的 Ruby 线程会被阻塞 吗?(也就是说 FXRuby 会不会在获取事件时阻塞?)

Lyle Johnson: 在 FXRuby 中处理线程一直是个问题,这要归咎于 Ruby 的线程实现机制。我一直不愿要求用户去使用打补丁的 FOX 或者 Ruby,所以我们不得不想一些 办法来应付这两个系统上的事件循环。基本上,我们所做的就是每当我们的 GUI 有一些空闲时间,我们就让 FXRuby 做一些杂事,由此从 Ruby 线程调度器 那获得一点时间片。没错,如果一个 Ruby 线程遇到一个阻塞的调用,FXRuby 也会被阻塞。而另一方面,在实践中,Ruby 线程应该不会被 FXRuby 所阻塞——尽管在理论上是有可能发生的,比如事件循环一直非常忙,以至于根本释放不出空闲时间。不过这也意味着程序的代码出了问题,应该先加以解决。



InfoQ: Ruby 1.9 的线程系统(本地线程 + 大 VM 锁)需要什么改变吗?还是它已经提供了以前不曾提供的特性(对 FXRuby 来说)?

Lyle Johnson: 对 FXRuby 来说,Ruby 1.9 只需要再做一点点改进就能够支持我们在 Ruby 1.8 中使用的基本方法。但我认为 Ruby 1.9 的线程系统可能提供了一些过去不可能有的机会。我会先尽可能详细地了解 1.9 的线程实现机制,然后再开始改进,并且会时刻记住,一定要保证对 Ruby 1.8 的向后兼容性(也就是说,要是 FXRuby 在 Ruby 1.9 上运行的快一点还好,但如果用起来差别很大是绝对不行的)。



InfoQ: FXRuby 和 FOX 工具包的布局管理策略是什么?能不能与其它工具包对比一下(不要过于强调 FOX 更好或者更糟,但也要提一下,这样才能让读者知道应该 用什么样的布局管理器)?你是否已经有了一些办法,或者知道一些办法让布局管理更加容易呢?比如,使用 Builder 记法(notation),或者使用 像Profligacy 的 LEL这样的东西。

Lyle Johnson: FOX 提供了很多不同种类的布局管理器,从最基本的需求,到窗体里整齐排列小部件,还有更复杂的情况(例如分割面板和滚动窗口)。在管理布局的办法上, FOX 和其它工具包最大的区别在于:在 FOX 中,布局管理器实际上就是部件,和其他部件一样。首先创建一个指定父部件(容器)的子部件,然后设置这些子部 件的布局属性,来告诉父部件如何来布置它们(例如,这个子部件要达到横向最大宽度,而那个子部件要保持固定的宽度)。

对于喜欢交互式 GUI 布局工具的人来说,可以使用 Meinrad Recheis 的foxGUIb。很多人都想为 GUI 布局提供一种 DSL,但是据我了解,还没有人真正开始做。Lance Carlson 的Anvil项目(正是为了此问题)看起来很有前途,但仍处于起步阶段。

InfoQ: 除了 Ruby 1.8.x,你还在别的 Ruby 版本上测试 FXRuby 了吗?比如 Ruby 1.9,或者像 Rubinius 和 MacRuby 这样系统?这些系统有没有什么特性——不管在哪方面——能让 FXRuby 表现地更好呢?

Lyle Johnson: FXRuby 已经可以在 Ruby 1.9 上工作了,但我还不知道有多少人真正从中体会到了它的优势。我刚刚开始考虑如何去支持 Rubinius,但它肯定是我下一个要支持的平台。 MacRuby 也不是不可能。我只是还不知道会有什么技术问题,或者说,在这一点上,支持这一平台究竟有多大意义(要知道它只能运行在 Mac OS X 上)。当然,还有一些其他平台,比如 JRuby 和 IronRuby,出于它们的实现方法,我恐怕不会支持它们了。



你可以获得由The Pragmatic Programmers出版的《FXRuby:用 Ruby 创建精简的 GUI》全书(PDF 和打印版都有)。

阅读英文原文:《Book Excerpt and Interview: FXRuby: Create Lean and Mean GUIs with Ruby