Qt源码分析-事件如何触发信号

来源:互联网 发布:ubuntu 16.04 jdk1.7 编辑:程序博客网 时间:2024/06/06 06:38
/*信号触发点
在分析Qt的事件循环时,在Windows平台的事件分发器处理函数
QEventDispatcherWin32::processEvents中最终只有DispatchMessage(&msg);
来分发事件,并没有看到怎么触发信号的,所以想了解事件到底怎么转换成信号的

猜测,是Qt的GUi组件封装了Windows的组件,然后接受事件消息,调用事件函数时去发射信号

分析一个按钮的click信号吧
一般应该是在mouseReleaseEvent里触发的,一层一层看怎么处理的*/

void QWidget::mouseReleaseEvent(QMouseEvent *event)  //注意是虚函数
{
    event->ignore();//可以看到QWidget仅仅是忽略信号
}

//=========================QAbstractButton::mouseReleaseEvent====================
//再看派生自QWidget的QAbstractButton,他又是QPushButton的基类

void QAbstractButton::mouseReleaseEvent(QMouseEvent *e)//虚函数
{
    Q_D(QAbstractButton);
    d->pressed = false;

    if (e->button() != Qt::LeftButton) {
        e->ignore();
        return;
    }

    if (!d->down) {
        e->ignore();
        return;
    }

    if (hitButton(e->pos())) {//返回基于当前接受事件的控件的局部坐标的点击位置,表示是否点击到这个控件
        d->repeatTimer.stop();
        d->click();//这里调用QAbstractButtonPrivate::click()函数
        e->accept();
    } else {
        setDown(false);
        e->ignore();
    }
}

//=========================QAbstractButtonPrivate::click()====================

void QAbstractButtonPrivate::click()//不是虚函数
{
    Q_Q(QAbstractButton);


    down = false;
    blockRefresh = true;
    bool changeState = true;
    if (checked && queryCheckedButton() == q) {
        // the checked button of an exclusive or autoexclusive group cannot be unchecked
#ifndef QT_NO_BUTTONGROUP
        if (group ? group->d_func()->exclusive : autoExclusive)
#else
        if (autoExclusive)
#endif
            changeState = false;
    }


    QPointer<QAbstractButton> guard(q);
    if (changeState) {
        q->nextCheckState();
        if (!guard)
            return;
    }
    blockRefresh = false;
    refresh();
    q->repaint(); //flush paint event before invoking potentially expensive operation
    QApplication::flush();
    if (guard)
        emitReleased();
    if (guard)
        emitClicked();//这里调用emitClicked发射信号
}

//=========================QAbstractButtonPrivate::emitClicked()====================

void QAbstractButtonPrivate::emitClicked()
{
    Q_Q(QAbstractButton);
    QPointer<QAbstractButton> guard(q);
    emit q->clicked(checked);//q就是QAbstractButton,就是说触发QAbstractButton的信号
#ifndef QT_NO_BUTTONGROUP
    if (guard && group) {
        emit group->buttonClicked(group->id(q));
        if (guard && group)
            emit group->buttonClicked(q);
    }
#endif
}

//====================重写QPushButton的mouseReleaseEvent函数======================

//而QPushButton没有实现mouseReleaseEvent函数,也没有click信号,所以必然依赖的时父类QAbstractButton的
//尝试覆盖这个函数试试mouseReleaseEvent,然后看有没有click信号发出
void MyPushButton::mouseReleaseEvent ( QMouseEvent * e )
{
    qDebug("My PushButton mouseRelease");
    QPushButton::mouseReleaseEvent(e);
}

/*结论就是
当把QPushButton::mouseReleaseEvent(e);注释掉时,是不会触发Click信号的
而,加上后,则会触发
即事件转换成信号,是由QEventDispatcherWin32::processEvents函数中
调用DispatchMessage(&msg);分发事件,然后调用相应事件函数(回调函数)
然后事件函数中会触发相应信号
所以切记重新相应事件函数时,记得调用基类的事件函数
*/
0 0
原创粉丝点击