Qt 信号与槽研究:
author: hjjdebug
date: 2015年 08月 17日 星期一 09:36:31 CST
----------------------------------------
先看看简单的源码:
----------------------------------------
mainwindow.h, mainwindow.cpp
#ifndef _MAINWINDOW
#define _MAINWINDOW
#include <QWidget>
class QPushButton;
class MainWindow : public QWidget
{
Q_OBJECT
public:
MainWindow(QWidget *parent=0);
public slots:
void button_click();
private:
QPushButton *button;
};
#endif
#include <QPushButton>
#include "mainwindow.h"
MainWindow::MainWindow(QWidget *widget)
: QWidget(widget)
{
button = new QPushButton(this);
button->setText("Push Me");
connect(button,SIGNAL(clicked()),this,SLOT(button_click()));
}
void MainWindow::button_click()
{
qDebug("button clicked");
}
//main.cpp
#include <QApplication>
#include "mainwindow.h"
int main(int argc,char *argv[])
{
QApplication a(argc,argv);
MainWindow w;
w.show();
return a.exec();
}
该代码可以实现点击button, 调用显示button_click 信息
下面分析三个方面:
----------------------------------------
1. Q_OBJECT 宏
----------------------------------------
public: template <typename T> inline
void qt_check_for_QOBJECT_macro(const T &_q_argument) const
{
int i = qYouForgotTheQ_OBJECT_Macro(this, &_q_argument);
i = i + 1;
}
static const QMetaObject staticMetaObject;
virtual const QMetaObject *metaObject() const;
virtual void *qt_metacast(const char *);
static inline QString tr(const char *s, const char *c = 0) { return staticMetaObject.tr(s, c); }
static inline QString trUtf8(const char *s, const char *c = 0) { return staticMetaObject.trUtf8(s, c); }
static inline QString tr(const char *s, const char *c, int n) { return staticMetaObject.tr(s, c, n); }
static inline QString trUtf8(const char *s, const char *c, int n) { return staticMetaObject.trUtf8(s, c, n); }
virtual int qt_metacall(QMetaObject::Call, int, void **);
private:
__attribute__((visibility("hidden"))) static const QMetaObjectExtraData staticMetaObjectExtraData;
__attribute__((visibility("hidden"))) static void qt_static_metacall(QObject *, QMetaObject::Call, int, void **);
注意:
声明了staticMetaObject 对象, 由moc_mainwindow.cpp 根据MainWindow 的信号,槽来实现
声明了staticMetaObjectExtraData , 包含qt_static_metacall 等函数
声明了一些函数接口,公共接口为qt_metacast, qt_metacall, metaObject() 等
----------------------------------------
2. moc_mainwindow.cpp
由于声明了Q_OBJECT, 而由工具moc 自动生成对应的moc代码
----------------------------------------
内容较多,不便贴出,请参考具体代码,
目的,实现Q_OBJECT 声明的内容, 完成QT 信号与槽对接。
----------------------------------------
3. 信号与槽的链接
我们只需要知道,信号经过一个长长的路程,依靠moc 代码,最后找到了它的归宿。
看#1, _o 传递了MainWindow 对象的this 指针, 神奇吧?!, 显然是曾经向qobject 注册过.
_c 指明了是InvokeMetaMethod,
_id 说是0, 显然它声称就是要调用注册的button_click 函数,
_a 好像在这里没有用到
----------------------------------------
Breakpoint 2, MainWindow::button_click (this=0x7f4000) at mainwindow.cpp:14
14 qDebug("button clicked");
(gdb) bt
#0 MainWindow::button_click (this=0x7f4000) at mainwindow.cpp:14
#1 0x000000000040292e in MainWindow::qt_static_metacall (_o=0x7f4000, _c=QMetaObject::InvokeMetaMethod, _id=0, _a=0x7fffffffd0e0)
at moc_mainwindow.cpp:48
#2 0x00007ffff6dd387a in QMetaObject::activate(QObject*, QMetaObject const*, int, void**) ()
from /usr/lib/x86_64-linux-gnu/libQtCore.so.4
#3 0x00007ffff793f0d2 in QAbstractButton::clicked(bool) () from /usr/lib/x86_64-linux-gnu/libQtGui.so.4
#4 0x00007ffff76a29d3 in ?? () from /usr/lib/x86_64-linux-gnu/libQtGui.so.4
#5 0x00007ffff76a3b43 in ?? () from /usr/lib/x86_64-linux-gnu/libQtGui.so.4
#6 0x00007ffff76a3c2c in QAbstractButton::mouseReleaseEvent(QMouseEvent*) () from /usr/lib/x86_64-linux-gnu/libQtGui.so.4
#7 0x00007ffff734050a in QWidget::event(QEvent*) () from /usr/lib/x86_64-linux-gnu/libQtGui.so.4
#8 0x00007ffff72f0e2c in QApplicationPrivate::notify_helper(QObject*, QEvent*) () from /usr/lib/x86_64-linux-gnu/libQtGui.so.4
#9 0x00007ffff72f75dd in QApplication::notify(QObject*, QEvent*) () from /usr/lib/x86_64-linux-gnu/libQtGui.so.4
#10 0x00007ffff6dbf4dd in QCoreApplication::notifyInternal(QObject*, QEvent*) () from /usr/lib/x86_64-linux-gnu/libQtCore.so.4
#11 0x00007ffff72f6d93 in QApplicationPrivate::sendMouseEvent(QWidget*, QMouseEvent*, QWidget*, QWidget*, QWidget**, QPointer<QWidget>&, bool) () from /usr/lib/x86_64-linux-gnu/libQtGui.so.4
#12 0x00007ffff736b9cb in ?? () from /usr/lib/x86_64-linux-gnu/libQtGui.so.4
#13 0x00007ffff736b269 in QApplication::x11ProcessEvent(_XEvent*) () from /usr/lib/x86_64-linux-gnu/libQtGui.so.4
#14 0x00007ffff7392b02 in ?? () from /usr/lib/x86_64-linux-gnu/libQtGui.so.4
#15 0x00007ffff5a31e04 in g_main_context_dispatch () from /lib/x86_64-linux-gnu/libglib-2.0.so.0
#16 0x00007ffff5a32048 in ?? () from /lib/x86_64-linux-gnu/libglib-2.0.so.0
#17 0x00007ffff5a320ec in g_main_context_iteration () from /lib/x86_64-linux-gnu/libglib-2.0.so.0
#18 0x00007ffff6dec7a1 in QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) ()
from /usr/lib/x86_64-linux-gnu/libQtCore.so.4
#19 0x00007ffff7392bb6 in ?? () from /usr/lib/x86_64-linux-gnu/libQtGui.so.4
#20 0x00007ffff6dbe0af in QEventLoop::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) ()
from /usr/lib/x86_64-linux-gnu/libQtCore.so.4
#21 0x00007ffff6dbe3a5 in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) () from /usr/lib/x86_64-linux-gnu/libQtCore.so.4
#22 0x00007ffff6dc3b79 in QCoreApplication::exec() () from /usr/lib/x86_64-linux-gnu/libQtCore.so.4
#23 0x00000000004026b7 in main (argc=1, argv=0x7fffffffde48) at main.cpp:9
(gdb)