JUCE复合控件之Toolbar

Toolbar工具栏不仅可以放置并显示常规的工具栏按钮(带图标和文字说明),还可以放置任意类型的控件,比如:组合框、列表框、文本标签、推子、弹出式菜单等等,甚至可以放置各类自定义的组件。也就是说:工具栏可为一个定制的组件,包含可绘制按钮或图像按钮,以及其他控件。

带图像按钮的常规工具栏所需的类有4个:

1、ToolbarItemFactory工具栏项目工厂类。该类负责产生工具栏所需的各个组件(按钮),包括分隔符,即该类负责创建ToolbarItemComponent类的对象。此类是抽象基类,派生类需实现3个纯虚函数,该类除构造函数和析构函数外,也只有这3个纯虚函数:

// 本类所能创建的所有项目的ID,即将一组不重复的整型ID添加到该函数的参数数组中
void getAllToolbarItemIds (Array& ids);	
/* 工具栏中所显示的项目,可以不添加某个项目的ID,也可以重复添加某个ID,比如分隔符。但不能添加上一个函数所返回的数组中所没有的ID值,也不能添加0值。因此,为了确保统一,ID最好使用本类中定义的枚举来助记,第一个枚举从1开始编号。如果枚举定义在public区,则在使用了本类对象的别的类中也能使用 */
void getDefaultItemSet (Array& ids);
/* 核心函数,根据参数ID的值,使用switch或if语句,创建并返回ID所对应的工具栏按钮组件(或自定义组件)。返回之前,所创建的工具栏按钮要绑定捕获器。 */
ToolbarItemComponent* createItem (int itemId);

2、ToolbarButton工具栏按钮类。ToolbarItemComponent的派生类,ToolbarItemFactory工具栏项目工厂类的createItem ()函数可创建并返回ToolbarItemComponent类型的指针对象。ToolbarButton的构造参数有4个,分别是:

  • 1参:按钮的ID,即createItem()函数的参数。
  • 2参:按钮的文本(工具栏中可显示在按钮下方,或者仅显示此文本)。
  • 3参:按钮在常规状态下所使用的Drawable对象(实质是按钮所显示的图像)。
  • 4参:按钮在开启(Toggle)状态下所使用的Drawable对象(图像),如果无需,则置为nullptr。

由此可知,如需让ToolbarItemFactory创建其他类型的工具栏项目,比如组合框、文本框、推子、其他类型的按钮等等,需自定义ToolbarButton的平级类,即这些自定义的工具栏项目类需继承自ToolbarItemComponent类。其具体写法可参照ToolbarButton类。

3、Drawable可绘制类。该类的静态函数createFromImageData()负责将图像数据转换为可绘制对象,转换后的可绘制对象为ToolbarButton工具栏按钮类的构造参数。该类的详解参见前文。

以上3个类全部集中于ToolbarItemFactory工具栏项目工厂类的派生类中,其中后两个类集中于核心函数createItem ()中。如需自定义组件或其他控件作为工具栏项目,则将工具栏按钮类替换为其他有关的类。需注意,这些类均需继承自ToolbarItemComponent类,也就是工具栏项目工厂类的核心函数createItem ()所返回的类型。

4、Toolbar工具栏类。使用该类的对象同普通的控件对象,内容组件中声明本类的对象,构造函数中实例化之。在创建本类对象之前,内容组件需先创建工具栏项目工厂类的对象。而后,本类对象调用 addDefaultItems ()函数,添加工具栏项目工厂类的对象,设置工具栏的布局方式及其他属性。本类有两个核心函数,一是添加工具栏项目工厂类对象的addDefaultItems(),二是getItemComponent()根据给出的索引返回工具栏中对应的项目(比如工具栏按钮)。返回的结果作为按钮捕获处理函数的判断依据。

即:假设内容组件类或其他类继承了Button::listener类,则在该类的buttonClicked()函数中进行按钮点击的判断处理。需注意,Toolbar类的getItemComponent()函数的参数为项目ID,此处的ID与工具栏项目工厂类中的第一个函数中的ID并不一致,无论是值,还是个数,均不存在对应关系。所关联的是工厂类第二个函数中设置的所要显示的项目ID,而且,仅对应其顺序和个数,并不对应具体的ID值。也就是说,工厂类的ID仅在工厂类中所用,可以重复某些ID,比如分隔符。而工具栏中的项目ID则是按实际出现的工具栏项目进行对应,其值是唯一性的。每个分隔符也对应一个唯一的ID,从左至右,从0开始,一一对应。

更好的方式是,工具栏项目工厂类同时继承Button::listener类,既生产工具栏项目,又对自身的按钮点击事件进行判断处理。所要执行的某些类的函数,可使用该类的指针来调用,工厂类cpp源文件开头处包含该类的h头文件即可。

如果工具栏中是其他控件或自定义组件,则分别继承相应的捕获器。JUCE类库中,自身能够产生消息并需要捕获处理的类往往都有一个Listener嵌套类,该类负责外围类的消息捕获与判断处理,有一到多个纯虚函数或功能性函数,用来完成判断处理。而外围类则有绑定捕获器和解除绑定的函数,利用这两个函数绑定或解绑本类所嵌套的Listener。

为方便理解,给出代码示例(网站发布,略)。

ToolbarItemFactory类只有3个纯虚函数,该类负责创建工具栏中的项目,即ToolbarItemComponent对象,一个ToolbarItemComponent对象相当于工具栏中的一个控件(比如一个工具栏按钮),该类的对象由工具栏项目工厂ToolbarItemFactory负责创建,创建后的结果供工具栏Toolbar使用。ToolbarItemComponent是一个抽象基类,继承自Button类,因此,Button和Component类的所有属性和行为,该类全部拥有。

ToolbarItemComponent类新增的重要成员函数有
 getItemId () 返回该组件所代表的项目ID,此值由构造函数所设置
 getToolbar () 返回包含此组件的Toolbar对象
 isToolbarVertical () 如果所隶属的工具栏是垂直式的则返回true
 setStyle () 设置此项目的样式,比如仅显示图标或仅显示文本,或两者皆显示
 getStyle () 返回此项目的当前样式,返回值为Toolbar类的枚举类型
 getContentArea () 返回该项目所占用的区域,该区域用于显示按钮的图像或其它内容
 getToolbarItemSizes () 纯虚函数,必须返回该项目的大小
 paintButtonArea () 纯虚函数,自我绘制
 contentAreaChanged () 纯虚函数,内容区域改变后自动调用此函数

ToolbarButton是ToolbarItemComponent的派生类,该类除构造函数外,没有新增可供直接调用的成员函数。但增加了几个可供派生类重写的普通成员函数,通常很少再派生该类的子类,因此不再列举。

工具栏双类配合模式中的Toolbar类代表工具栏组件,相当于工具栏项目(控件)的容器。该类继承自Component、DragAndDropContainer拖放容器、DragAndDropTarget拖放目标这3个类。Toolbar预定义了3种枚举类型,常用的是工具栏项目的样式枚举:
 Toolbar::iconsOnly 仅显示图标
 Toolbar::iconsWithText 图标下方显示文本
 Toolbar::textOnly 显示每个项目的文本

Toolbar类的重要成员函数(略)

一个自定义的ToolbarItemComponent工具栏项目类(出现在工具栏中的组合框)代码示例(略)