JUCE复合控件之TableListBox详解

TableListBox以表格的形式显示各类数据,而数据来源与显示(绘制)则由抽象基类TableListBoxModel来完成。因此,内容组件类如使用表格控件,需继承TableListBoxModel类并实现其纯虚函数,而后在类中声明TableListBox表格对象。通常还需要一个TableHeaderComponent表头类(每一列的标头,用于显示列标题,添加或移除列,本列数据排序等)。注意:表格中的某一列可使用自定义的组件,比如组合框。。

使用表格6步走

1、内容组件继承TableListBoxModel,作为表格的数据来源并完成数据的显示:

class TableDemoComponent : public Component, 
                           public TableListBoxModel

2、内容组件中添加函数,用于获取要显示的数据。比如:

// 此函数将XML文件的数据加载到内存中
void loadData()
{
    // 定义XML文档对象并初始化为已嵌入代码中的XML文档数据
    XmlDocument dataDoc (String ((const char*) 
                         BinaryData::demo_table_data_xml));

    // 数据成员demoData(XML节点对象)赋值为XML文档的根节点
    demoData = dataDoc.getDocumentElement();

    // 设置行对象。getChildByName()的作用是:返回与给定名称相同的第一个子节点。
    dataList = demoData->getChildByName ("DATA");

    // 设置列对象
    columnList = demoData->getChildByName ("COLUMNS");

    // 行数为根节点的所有子节点的个数
    numRows = dataList->getNumChildElements();
}

通常,将所需的数据赋值给本类的某个或某些数据成员,比如示例中的XML节点对象或数组对象。

3、内容组件中声明表格对象:

TableListBox table;

4、内容组件的构造函数中加载数据,添加显示表格对象,并设置其有关属性(代码略):

5、内容组件类实现基类的3个纯虚函数。这三个纯虚函数的作用分别为:获取表格的行数;绘制每行的背景;将数据显示(绘制)到单元格中(g.drawText()函数用于绘制数据,具体流程是:先获取某行的数据,而后获取该行某列的数据,这样即可保证每个单元格的数据都是一一对应的,通常采用循环结构完成此事)。如有需要,重写基类的其他功能性函数。比如:点击表头某列,该列自动排序;设置每一列的最佳宽度等等。示例:(代码略)

通常,内容组件需重写Component类的visibilityChanged()函数,可视状态变化时,更新表格内容:

// 可视与否改变时,表格对象更新内容
void BaseComp::visibilityChanged()
{
    if (isVisible())
        table->updateContent();
}

TableListBox继承自ListBox和ListBoxModel等类,因此,拥有这两个类的所有属性和行为。

TableListBox类的重要成员函数:(略)

TableBoxModel类是一个独立的类,无基类。该类的重要成员函数:(略)

TableHeaderComponent继承自Component类和AsyncUpdater类。该类的表头属性枚举(略):

TableHeaderComponent类的重要成员函数(略):

小技巧:表格的单元格使用自定义组件(比如表格中某列全部为ComboBox)

继承了TableListBoxModel的内容组件类重写基类的纯虚函数refreshComponentForCell():

// 创建或更新单元格内的组件
Component* refreshComponentForCell (int rowNumber, int columnId, 
                                    bool isRowSelected, 
                                    Component* existingComponentToUpdate)
{
    if (columnId != 4)  // 只是第5列的单元格使用自定义组件(列索引从0开始)
        return nullptr;

    // 如果本函数的4参为空,则创建自定义的单元格组件
    if (existingComponentToUpdate == nullptr)
        existingComponentToUpdate = new MyComp();

    // 创建后,自定义组件可调用自己的成员函数,进行某些处理、更新或设置
    MyComp* myComp = dynamic_cast<MyComp*> (existingComponentToUpdate);

    if (myComp != nullptr)
        myComp->doSomething();

    // 返回4参
    return existingComponentToUpdate;
}