870920 Menu

JUCE程序的外观总控:LookAndFeel

LookAndFeel是JUCE类库中所有可视化组件(控件。含控件所显示的字型、字体等)的外观“总控”。程序中可以设置全局性的LookAndFeel,某个组件也可以设置自己的LookAndFeel,两者的区别主要是所调用的设置函数不同。全局性设置LAF的函数是LookAndFeel类的静态函数setDefaultLookAndFeel(),可在程序主体类的初始化函数中完成设置。而组件设置自己的LAF可在上级组件的构造函数中使用setLookAndFeel(),或者在自身的构造函数中调用此函数(如果是程序员自定义的组件、控件类)。

JUCE自带了三套LAF。可根据需要,派生自己的LAF类。曾听到有用户抱怨,JUCE控件的样式与风格与当前平台下的原生控件不同。实际上这种理念狭隘、落后而僵化。通过派生自己的LAF类,可以实现任何样式和风格的控件外观,完全可以随心所欲,自由创造。模仿任何平台的原生控件当然不在话下。不过,无论Windows,OSX,还是Linux桌面,在笔者(Running)看来,一个比一个丑陋、呆板、单调,实在令人昏昏欲睡。不如发挥自己的想象力和创造力,基于所开发的软件本身的功能、特点,甚至想带给用户的感官体验、意境、情绪等等,搞出更加艺术、个性鲜明、量身打造的样式与风格。这才是GUI编程的总原则和大趋势,更是让冰冷的程序迈向“美学境界”最直接、最立竿见影的做法。

总的来说,JUCE类库在GUI方面使用LAF这一机制,实在比平台原生的那套默认定死的玩意儿先进、自由、简单多了。

实际上,这也是跨平台类库设计理念的不同。有些跨平台类库的GUI控件外观完全依照平台原生的(或者干脆就是通过调用平台自身的SDK来实现);有些则尽力模仿、中和与协调不同平台下的外观差异,同时小心翼翼地拿出自己的外观样式。而JUCE类库,在此方面显然比较大胆、前卫和“任性”,更加开放、包容和面向未来。

如需在程序中显示或输入非英语文字,办法很多,简单做法可在自定义的LAF或程序主体类的初始化函数中指定平台相关的“字体”,这些东西都是平台特定和平台依赖的,与类库本身并无关系。或干脆指定自己嵌入程序代码中的个性字体。更可以为不同的组件和控件设置其独有的字型与字体。有用户曾抱怨JUCE对日文、俄文、中文等“支持”不够,这个论调实在奇哉怪也。真的不应该是一个基本合格的程序员,特别是跨平台开发者所应该说出的话。

我还看到过有母语非英语系的JUCE程序员在处理字型、字体等问题时,采取了修改类库源码的策略。不得不说,这个主意实在糟透了。一是完全没必要。二是使用类库,特别是开源的、跨平台的类库,有一大禁忌和须知:任何情况下,绝不要动源码。排除其他显而易见的因素,这里还有一个尊重作者、敬畏知识产权的道德与法律问题。如果类库本身确实有BUG或设计不合理,可以提交、反馈自己的解决方案,或者联系作者,详述意见。实在来不及,可以参照原代码,重写一个新类,用到自己的项目中。

LAF中指定平台相关、无关或内嵌的字体,通常可使用JUCE的“平台宏”进行判断和包裹,使程序在所有平台下,所显示的文字样式与大小保持基本一致。

注意一点:一个正规、严肃的C++跨平台项目,特别是开源项目,任何情况下,无论是否考虑到国际化,无论是否全球合作,均严禁在源代码文件中使用任何非标准字母或字符,包括注释。详情可参阅《编码样式与风格》一文(该文给出了英文水平较低时的解决方案)。如果确实不用不行,则将其转换为UTF-8字符串(Introjucer附带了一个转换工具,很方便),比如:“中文”这两个象形汉字转换为UTF-8字符串后为:

有些程序,需要完全仿真的界面和控件。实现思路很多,一个懒省事的做法是在总的或控件特定的LAF中使用图像技术,一了百了。下面的代码演示了一个仿真推子的外观自定义(基于图像技术,而非编码定制):

此外:JUCE类库更新很频繁,似乎每次大动作,Jules都要调整LAF基类(比如有些虚函数的参数类型和个数,甚至增删虚函数)。这样就导致一些个人派生的LAF,升级类库后需要不断调整和修改。如果说我本人对JUCE类库的LAF机制有何不满的话,就是这一点了。