QwtLegend类表征一个示例图容器部件【The legend widget.】,继承自QFrame。其上面使用QwtDynGridLayout动态排列了多个示例图,每个示例图可以是任何类型的QWidget窗体部件,但通常是QwtLegendItem。




  \param parent Parent widget
QwtLegend::QwtLegend( QWidget *parent ):
    QFrame( parent )
    setFrameStyle( NoFrame );

    d_data = new QwtLegend::PrivateData;
    d_data->itemMode = QwtLegend::ReadOnlyItem;

    d_data->view = new QwtLegend::PrivateData::LegendView( this );
    d_data->view->setObjectName( "QwtLegendView" );
    d_data->view->setFrameStyle( NoFrame );

    QwtDynGridLayout *gridLayout = new QwtDynGridLayout(
        d_data->view->contentsWidget );
    gridLayout->setAlignment( Qt::AlignHCenter | Qt::AlignTop );

    d_data->view->contentsWidget->installEventFilter( this );

    QVBoxLayout *layout = new QVBoxLayout( this );
    layout->setContentsMargins( 0, 0, 0, 0 );
    layout->addWidget( d_data->view );

class QwtLegend::PrivateData::LegendView: public QScrollArea

2)d_data->view->contentsWidget->installEventFilter( this );  在d_data->view->contentsWidget(是一个QWidget)安装事件过滤器this (是一个QScrollArea),即发送给 contentsWidget 的事件都会经过 this 的 eventFilter() 函数过滤。

3)d_data->view->contentsWidget 作为视口的窗体部件,也是所有示例图元的父部件。

    QWidget *contentsWidget();
    const QWidget *contentsWidget() const;

The contents widget is the only child of the viewport of the internal QScrollArea and the parent widget of all legend items.
       Container widget of the legend items。

2、在QwtLegend::PrivateData数据内部存储了QWidget(代表QwtLegend里的一个示例图元QwtLegendItem) 和 QwtLegendItemManager (代表画布QwtCanvas里的一个图元QwtPlotItem)的映射关系。

        QMap<QWidget *, const QwtLegendItemManager *> d_widgetMap;
        QMap<const QwtLegendItemManager *, QWidget *> d_itemMap;

    void insert( const QwtLegendItemManager *, QWidget * );
    void remove( const QwtLegendItemManager * );

    QWidget *find( const QwtLegendItemManager * ) const;
    QwtLegendItemManager *find( const QWidget * ) const;

    virtual QList<QWidget *> legendItems() const;


  Handle QEvent::ChildRemoved andQEvent::LayoutRequest events 
  for the contentsWidget().

  \param object Object to be filtered
  \param event Event
bool QwtLegend::eventFilter( QObject *object, QEvent *event )
    if ( object == d_data->view->contentsWidget )
        switch ( event->type() )
            case QEvent::ChildRemoved: // 删除子项事件,Qt内部事件
                const QChildEvent *ce = 
                    static_cast<const QChildEvent *>(event);
                if ( ce->child()->isWidgetType() )
                    QWidget *w = static_cast< QWidget * >( ce->child() );
                    d_data->map.remove( w );
            case QEvent::LayoutRequest: // 布局请求事件,Qt内部事件

    return QFrame::eventFilter( object, event );
如果要处理用户自定义事件,则需要自己定义事件类 UserEvent :

class UserEvent : public QEvent
    static const QEvent::Type eventType;

    explicit UserEvent () : QEvent(eventType) { }

    QString m_userName;
    int m_userAge;
    double m_userSalary;
在对应的源文件中初始化  static const QEvent::Type eventType;

const QEvent::Type UserEvent::eventType = static_cast<QEvent::Type>(QEvent::registerEventType());
这样就可以在eventFilter()函数中处理/过滤自定义事件UserEvent 了。


1) bool QCoreApplication::sendEvent ( QObject * receiver, QEvent * event )   [static]

    virtual bool viewportEvent( QEvent *e )
        bool ok = QScrollArea::viewportEvent( e );

        if ( e->type() == QEvent::Resize )
            QEvent event( QEvent::LayoutRequest );
            QApplication::sendEvent( contentsWidget, &event ); // 发送事件,函数要在该事件被处理后才返回
        return ok;

bool QCoreApplication::sendEvent ( QObject * receiver, QEvent * event )   [static]

Sends event event directly to receiver receiver, using the notify() function. Returns the value that was returned from the event handler.
The event is not deleted when the event has been sent. The normal approach is to create the event on the stack, for example:

 QMouseEvent event(QEvent::MouseButtonPress, pos, 0, 0, 0);
 QApplication::sendEvent(mainWindow, &event);
See also postEvent() and notify().

2)void QCoreApplication::postEvent ( QObject * receiver, QEvent * event, int priority )   [static]

    if ( parentWidget() && parentWidget()->layout() == NULL )
           updateGeometry() doesn't post LayoutRequest in certain
           situations, like when we are hidden. But we want the
           parent widget notified, so it can show/hide the legend
           depending on its items.
        QApplication::postEvent( parentWidget(),
            new QEvent( QEvent::LayoutRequest ) ); // 发送事件至接收器的事件队列中(可能不会被立即执行)

void QCoreApplication::postEvent ( QObject * receiver, QEvent * event )   [static]

Adds the event event, with the object receiver as the receiver of the event,to an event queueand returns immediately.
The event must be allocated on the heap since the post event queue will take ownership of the event and delete it once it has been posted.It is not safe to modify or delete the event after it has been posted.
When control returns to the main event loop, all events that are stored in the queue will be sent using the notify() function.
Events are processed in the order posted. For more control over the processing order, use the postEvent() overload below, which takes a priority argument. This function posts all event with a Qt::NormalEventPriority.
Note: This function is thread-safe.
See also sendEvent(), notify(), and sendPostedEvents().