在Qt中使用回调函数替代信号槽

迷南。 2022-05-22 09:45 396阅读 0赞

前言

在Qt中传数据,我们使用了一个信号和槽系统,但这并不意味着不能使用旧的经过验证的方法,即使用 CallBack回调函数功能。
事实上使用 CallBack 功能比信号和槽要快一些。并且当发送信号的对象在程序中被销毁并且不再使用时,就信号理想地从槽中分离而言,回调可以更容易使用。


如何使用CallBack工作

假设A类包含B类的对象,B类有动作时想要通知到A类,B类应该有个设置回调函数的接口,A类应该定义相应的回调函数,将函数指针传递给B。

还是直接举例吧:
例如,将使用一个类,在图形场景中绘制一个正方形,并由W,A,S,D键控制。移动时,正方形必须将其坐标的数据发送到创建它的类。也就是说,它应该把这个类的函数作为它的 CallBack 函数。要做的程序效果如下,通过WASD控制方块移动,主窗口接收正方形的位置信息,并将位置信息填入QLineEdit:
这里写图片描述


程序及解释

源码存放路径

  1. https://github.com/lesliefish/Qt/tree/master/Project/QtGuiApplication/CallBackTest

为了熟悉 CallBack 的工作 ,我们使用具有以下结构的项目:
• mainwindow.h - 主应用程序窗口的头文件;
• mainwindow.cpp - 主应用程序窗口的源文件;
• square.h - 其对象将使用 CallBack 函数的类的头文件 。
• square.cpp - 给定类的源代码文件;


square.h中部分代码:

  1. class Square : public QObject, public QGraphicsItem
  2. {
  3. Q_OBJECT
  4. public:
  5. explicit Square(QObject *parent = 0);
  6. ~Square();
  7. // 设置回调函数的函数
  8. void setCallbackFunc(void(*func) (QPointF point));
  9. protected:
  10. QRectF boundingRect() const;
  11. void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
  12. private:
  13. QTimer * m_timer;
  14. void(*m_callbackFunc)(QPointF point);
  15. private slots:
  16. void slotTimer();
  17. };

square.cpp中部分代码:

  1. Square::Square(QObject *parent)
  2. : QObject(parent), QGraphicsItem()
  3. {
  4. m_timer = new QTimer();
  5. connect(m_timer, &QTimer::timeout, this, &Square::slotTimer);
  6. m_timer->start(1000 / 33);
  7. }
  8. Square::~Square()
  9. {
  10. }
  11. void Square::setCallbackFunc(void(*func) (QPointF point))
  12. {
  13. m_callbackFunc = func;
  14. }
  15. QRectF Square::boundingRect() const
  16. {
  17. return QRectF(-15, -15, 30, 30);
  18. }
  19. void Square::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
  20. {
  21. painter->setPen(Qt::black);
  22. painter->setBrush(Qt::green);
  23. painter->drawRect(-15, -15, 30, 30);
  24. Q_UNUSED(option);
  25. Q_UNUSED(widget);
  26. }
  27. void Square::slotTimer()
  28. {
  29. // 根据按钮触发情况移动正方形
  30. if (GetAsyncKeyState('A'))
  31. {
  32. this->setX(this->x() - 2);
  33. }
  34. if (GetAsyncKeyState('D'))
  35. {
  36. this->setX(this->x() + 2);
  37. }
  38. if (GetAsyncKeyState('W'))
  39. {
  40. this->setY(this->y() - 2);
  41. }
  42. if (GetAsyncKeyState('S'))
  43. {
  44. this->setY(this->y() + 2);
  45. }
  46. // 调用回调函数传递正方形位置 类似于发信号给mainwindow 由mainwindow执行相应槽函数
  47. m_callbackFunc(this->pos());
  48. }

mainwindow.h部分代码

  1. class MainWindow : public QWidget
  2. {
  3. Q_OBJECT
  4. public:
  5. explicit MainWindow(QWidget *parent = Q_NULLPTR);
  6. ~MainWindow();
  7. private:
  8. Ui::MainWindow* ui;
  9. QGraphicsScene* m_scene;
  10. Square *m_square; // 声明正方形 传输回调
  11. static QLineEdit *line1; // 声明一个静态QLineEdit, 执行回调
  12. static QLineEdit *line2; // 声明一个静态QLineEdit, 执行回调
  13. private:
  14. // 声明一个回调函数
  15. static void getPosition(QPointF point);
  16. };

mainwindow.cpp部分代码

  1. QLineEdit * MainWindow::line1;
  2. QLineEdit * MainWindow::line2;
  3. MainWindow::MainWindow(QWidget *parent)
  4. : QWidget(parent)
  5. {
  6. ui = new Ui::MainWindow();
  7. ui->setupUi(this);
  8. // 初始化QLineEdit
  9. line1 = new QLineEdit();
  10. line2 = new QLineEdit();
  11. // 把两个line 放进gridLayout
  12. ui->gridLayout->addWidget(line1, 0, 1);
  13. ui->gridLayout->addWidget(line2, 0, 2);
  14. // 初始化图形场景
  15. m_scene = new QGraphicsScene();
  16. // 设置场景到 graphicsView
  17. ui->graphicsView->setScene(m_scene);
  18. m_scene->setSceneRect(0, 0, 300, 300);
  19. m_square = new Square();
  20. // 将getPosition设置回调 接收m_square传入的数据
  21. m_square->setCallbackFunc(getPosition);
  22. m_square->setPos(100, 100);
  23. m_scene->addItem(m_square);
  24. }
  25. MainWindow::~MainWindow()
  26. {
  27. delete ui;
  28. }
  29. /**
  30. * @fn MainWindow::getPosition
  31. * @brief 回调函数接收正方形位置 写入两个lineEdit
  32. * @param QPointF point
  33. * @return void
  34. */
  35. void MainWindow::getPosition(QPointF point)
  36. {
  37. line1->setText(QString::number(point.x()));
  38. line2->setText(QString::number(point.y()));
  39. }

原文地址:

  1. https://evileg.com/ru/post/89/

发表评论

表情:
评论列表 (有 0 条评论,396人围观)

还没有评论,来说两句吧...

相关阅读

    相关 QT信号机制

    信号槽 信号槽是QT中用于对象间通信的一种机制,也是QT的核心机制。在GUI编程中,我们经常需要在改变一个组件的同时,通知另一个组件做出响应。例如: ![0c21ac