QT 回调函数来龙去脉

拜拜、爱过 提交于 2019-12-24 21:33:43

一、回调函数
  回调函数就是一个通过函数指针调用的函数。A类将一个函数的地址作为参数传给B类的一个函数,此时A类就不用关心这个函数的执行了。当B类里面触发了某个特定的条件,B类调用这个回调函数,进行响应。

二、回调函数的例子
在这里插入图片描述
(1)主窗体

//MainWindow.h
public:
	//静态方法的回调函数
    static void setPos(MainWindow *m, const QPointF &r);
    void setLinePos(const QPointF &r);

//MainWindow.cpp------------------------------------------------------
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    //widget提升为了子部件
    //把对象实例的指针或引用做为参数传给子部件。就能找到主窗口中的控件。
    ui->widget->setCallbackFunc(this, setPos);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::setPos(MainWindow *m, const QPointF &r)
{
	//静态函数中,没有this指针,因此需要传当前对象,否则无法拿到lineEdit控件
    m->setLinePos(r);
}

void MainWindow::setLinePos(const QPointF &r)
{
    ui->lineEdit1->setText(QString::number(r.x()));
    ui->lineEdit2->setText(QString::number(r.y()));
}


(2)子部件

//Call.h
public:
    explicit Call(QWidget *parent = nullptr);
    ~Call();

    void setCallbackFunc(MainWindow *m, void(*func) (MainWindow *m, const QPointF &point));
protected:
    void paintEvent(QPaintEvent *event);
    void keyPressEvent(QKeyEvent *event);

private:
    void(*m_callbackFunc)(MainWindow *m, const QPointF &point);
    MainWindow *m_m;


//Call.cpp-----------------------------------------------------
Call::Call(QWidget *parent)
    :QWidget(parent)
{
    setFocusPolicy(Qt::StrongFocus);
}

Call::~Call()
{
}

void Call::setCallbackFunc(MainWindow *m,void(*func) (MainWindow *m, const QPointF &point))
{
	//保存回调函数地址,以及主窗口对象
    m_m = m;
    m_callbackFunc = func;
}

void Call::paintEvent(QPaintEvent *event)
{
    Q_UNUSED(event);

    //想要绘图生效,painter必须关联到画图设备,当前代码中画图设备为this(当前窗口)
    QPainter painter(this);
    painter.setPen(Qt::white);
    painter.setBrush(Qt::red);
    painter.drawRect(0, 0, 50, 50);
}

void Call::keyPressEvent(QKeyEvent *event)
{
	//获取键盘事件,事件触发后,进行移动
    switch(event->key())
    {
        case Qt::Key_Up:
            move(this->x(), this->y() - 20);
            break;
        case Qt::Key_Down:
            move(this->x(), this->y() + 20);
            break;
        case Qt::Key_Left:
            move(this->x() - 20, this->y());
            break;
        case Qt::Key_Right:
            move(this->x() + 20, this->y());
            break;
        default:
            break;
    }
	
	//子部件调用回调函数,将此时的部件坐标告诉对应的主窗口
    m_callbackFunc(m_m, this->pos());
}

三、回调函数为什么需要加static?
  在类中封装回调函数,回调函数必须要加上static关键字,这样this指针就不能用了,类中静态函数只能访问类的静态成员,不能访问类中的非静态成员,静态函数属于这个类,而不再仅仅属于具体的对象,类的静态函数中没有默认的this指针。但是为什么要这要做呢?

//1.例如一个回调函数被要求声明为以下形式(正确格式):
void CALLBACK function();

//2.如果这个函数在类ObjClass里面,编译器会为其添加一个this指针,
//用于指向调用该函数的对象。所以编译出来的代码是这种形式:

void CALLBACK ObjClass::function(ObjClass* this);

函数参数列表与被要求声明的形式不一致。就比如说,主窗口中回调函数中有this指针,但是子部件调用的时候可没有。没有了this,而我们也恰巧需要使用主窗口中的控件,我们可以把对象实例的指针或引用做为参数传给子部件。

参考各位大佬的文章,再次感谢!
百度百科:回调函数
喜欢吃冰棍de谷利文君:Qt错误:Painter not active
菌丶:类中的回调函数要加static的原因
云端的蜗牛:C++回调函数必须为静态函数的原因
lesliefish:在Qt中使用回调函数替代信号槽

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!