原文链接: [Richard Moe Gustavsen](http://labs.qt.nokia.com/author/richardmg/) - [Alien widgets on Mac](http://labs.qt.nokia.com/2011/02/23/alien-widgets-on-mac/)
直到现在,Qt/Mac 上的每个控件 (widget) 都还是由它们自己的 `NSView` 来支持的。这意味着,Qt 必须将你的程序里控件的层级结构完整映射到 Cocoa 中视图的父子层级结构中。每个 Cocoa 视图接受的本地事件都会被转发给对应的 Qt 控件。然后我们加以处理再重定向以实现 Qt 专门的逻辑,包括隐式或显式的鼠标捕获、弹出等等,最后这些事件再被转换为 QEvent 并以平台无关的方式发送给应用。
Apple 表示你得小心不能用多了 `NSView` ([参考](http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CocoaViewsGuide/Optimizing/Optimizing.html)),应该保证视图的数量在 100 以下以获得最优效率。这意味着在你创建重度使用控件的 Qt 应用时,你的应用很容易就会达到这个限制。这样的结果可能不太好,如第一个视频所示。所录的应用故意创建了 2000 个控件,每个都在鼠标经过的时候高亮按钮。如你所见,这个例子不能适应如此大量的控件,造成了很大的延迟。
因为我们知道有些客户确实在使用大量的控件来构建复杂的 UI,这样的限制有时是至关重要的。还好 Qt 针对这个问题有一套叫做 *Alien 控件* ([参考](http://labs.qt.nokia.com/2007/08/09/qt-invaded-by-aliens-the-end-of-all-flicker/)) 的解决方案。Alien 在 Qt 的 Windows 和 X11 版本中自从 Qt-4.4 就默认启用了,它基本上去掉了要求一个控件必须有一个本地窗口支持的限制。在 Mac 上,这可以转换为 Qt 不要求每个控件必须有一个 `NSView`。这样我们只要用到一个视图 (窗口的内容视图),然后自己把这个视图切分为多个控件,尽可能地跳过 Cocoa 的处理。
这么做的好处有三:其一,我们去掉了在事件达到应用程序之前必须执行的代码。比如不是让 Cocoa 先去找到对应鼠标按下的视图,然后在让 Qt 把事件转发到其他地方 (因为捕获、弹出之类),我们可以直接在 Qt 里处理按下事件;其二,既然大部分的事件处理已经可以从平台相关代码转向平台独立代码,我们希望 Qt/Mac 也能和其他平台保持同步;最后,我们现在遵循了 Apple 的建议不再使用过多的视图了。看来他们说的没错,这真的会拖慢应用。第二个视频展示了使用 Alien 的同一个例子,延迟完全不见了。
Alien 将会在 Qt-4.8 的 Mac (Cocoa) 版本默认启用。
(另外欢迎自己[下载](http://qt.gitorious.org/qt/qt/commits/master)并尝试 Mac 上的 Alien。)