Qt原始碼分析-事件如何觸發訊號
阿新 • • 發佈:2019-02-20
/*訊號觸發點
在分析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訊號發出
voidMyPushButton::mouseReleaseEvent ( QMouseEvent * e )
{
qDebug("My PushButton mouseRelease");
QPushButton::mouseReleaseEvent(e);
}
/*結論就是
當把QPushButton::mouseReleaseEvent(e);註釋掉時,是不會觸發Click訊號的
而,加上後,則會觸發
即事件轉換成訊號,是由QEventDispatcherWin32::processEvents函式中
呼叫DispatchMessage(&msg);分發事件,然後呼叫相應事件函式(回撥函式)
然後事件函式中會觸發相應訊號
所以切記重新相應事件函式時,記得呼叫基類的事件函式
*/
在分析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訊號發出
voidMyPushButton::mouseReleaseEvent ( QMouseEvent * e )
{
qDebug("My PushButton mouseRelease");
QPushButton::mouseReleaseEvent(e);
}
/*結論就是
當把QPushButton::mouseReleaseEvent(e);註釋掉時,是不會觸發Click訊號的
而,加上後,則會觸發
即事件轉換成訊號,是由QEventDispatcherWin32::processEvents函式中
呼叫DispatchMessage(&msg);分發事件,然後呼叫相應事件函式(回撥函式)
然後事件函式中會觸發相應訊號
所以切記重新相應事件函式時,記得呼叫基類的事件函式
*/