JUCE类库之PopupMenu 3-3

自定义菜单项(PopupMenu::CustomComponent)

如果要使用别具一格的自定义菜单项,则:

1、写一个类,继承自PopupMenu::CustomComponent类,如需动态绘制,可再继承Timer类,在timerCallback ()函数中修改paint()所需的有关数值,而后repaint()触发重绘。完整的示例如下:

// 自定义菜单项
class CustomMenuComponent : public PopupMenu::CustomComponent, 
                            public Timer 
{
public:
    // 构造函数:初始化数据成员,启动计时器
    CustomMenuComponent() : blobX (0), blobY (0)  
    { 
        startTimer (200);  // 创建本类对象即启动计时器
    }

    // 设置本组件最理想的大小,因形参为引用型int,故可在本函数中改变实参的值。
    // 此值将通知菜单,这两个值是最理想的宽度和高度。此函数是内部运作的,无需显式调用。
    void getIdealSize (int& idealWidth, int& idealHeight)  
    {
        // 宽度200像素,高度60像素
        idealWidth = 200;
        idealHeight = 60;
    }

    // 本组件的绘制方法,定义菜单项所显示的外观,本类的关键函数。
    void paint (Graphics& g) 
    {
        g.fillAll (Colours::yellow.withAlpha (0.3f));
        g.setColour (Colours::pink);

        /* 绘制一个实心椭圆,参数为椭圆的起点,宽高。注意,此处是先绘制背景,再绘制椭圆,最后再绘制文本。一个覆盖一个,顺序不能乱。 */
        g.fillEllipse ((float) blobX, (float) blobY, 30.0f, 40.0f);

        g.setFont (20.0f, Font::italic);
        g.setColour (Colours::black);

        // 绘制文本。参数:文本,起点x,y,宽,高,文字对齐方式,最多显示几行
        g.drawFittedText (L"此为定制的菜单项,跳动的椭圆是用计时器回调实现的",
                          4, 0, getWidth() - 8, getHeight(), 
                          Justification::centred, 3);
    }
  
    // 计时器回调。本例实现动画效果的关键
    void timerCallback() 
    {
        // 每次调用本函数均随机赋值,随机值的范围为0到本组件的最大宽度、最大高度。
        // 此函数将不停的repaint(),界面中就出现了椭圆跳来跳去的视觉效果
        blobX = Random::getSystemRandom().nextInt (getWidth());
        blobY = Random::getSystemRandom().nextInt (getHeight());

        repaint();  // 本组件刷新重绘,内部调用本类的paint()函数。
    }

private:
    int blobX, blobY;
};

2、弹出式菜单对象在有关方法中添加自定义菜单项(直接new了一个匿名堆对象):

m.addCustomItem (该菜单项的ID, new CustomMenuComponent());

因为继承自PopupMenu::CustomComponent类,该类有其内部的管理机制,所以自定义菜单项类的堆对象无需显式销毁,这一点非常方便。利用菜单项可添加自定义组件这一功能,可以实现很灵活的GUI交互,比如,弹出的菜单项为颜色选择组件、对话框窗口、实时更新绘制内容的组件等等。

应用程序主菜单功能,请参见后文MenubarModel一节。

PopupMenu类的重要成员函数及静态函数:(网站发布,略)

小技巧
 强制退出程序时,如果PopupMenu正在显示,将有可能导致程序崩溃。解决方案:在弹出菜单的类的析构函数中加一句:

PopupMenu::dismissAllActiveMenus();