在Qt中使用回调函数替代信号槽
前言
在Qt中传数据,我们使用了一个信号和槽系统,但这并不意味着不能使用旧的经过验证的方法,即使用 CallBack回调函数功能。
事实上使用 CallBack 功能比信号和槽要快一些。并且当发送信号的对象在程序中被销毁并且不再使用时,就信号理想地从槽中分离而言,回调可以更容易使用。
如何使用CallBack工作
假设A类包含B类的对象,B类有动作时想要通知到A类,B类应该有个设置回调函数的接口,A类应该定义相应的回调函数,将函数指针传递给B。
还是直接举例吧:
例如,将使用一个类,在图形场景中绘制一个正方形,并由W,A,S,D键控制。移动时,正方形必须将其坐标的数据发送到创建它的类。也就是说,它应该把这个类的函数作为它的 CallBack 函数。要做的程序效果如下,通过WASD控制方块移动,主窗口接收正方形的位置信息,并将位置信息填入QLineEdit:
程序及解释
源码存放路径
https://github.com/lesliefish/Qt/tree/master/Project/QtGuiApplication/CallBackTest
为了熟悉 CallBack 的工作 ,我们使用具有以下结构的项目:
• mainwindow.h - 主应用程序窗口的头文件;
• mainwindow.cpp - 主应用程序窗口的源文件;
• square.h - 其对象将使用 CallBack 函数的类的头文件 。
• square.cpp - 给定类的源代码文件;
square.h中部分代码:
class Square : public QObject, public QGraphicsItem
{
Q_OBJECT
public:
explicit Square(QObject *parent = 0);
~Square();
// 设置回调函数的函数
void setCallbackFunc(void(*func) (QPointF point));
protected:
QRectF boundingRect() const;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
private:
QTimer * m_timer;
void(*m_callbackFunc)(QPointF point);
private slots:
void slotTimer();
};
square.cpp中部分代码:
Square::Square(QObject *parent)
: QObject(parent), QGraphicsItem()
{
m_timer = new QTimer();
connect(m_timer, &QTimer::timeout, this, &Square::slotTimer);
m_timer->start(1000 / 33);
}
Square::~Square()
{
}
void Square::setCallbackFunc(void(*func) (QPointF point))
{
m_callbackFunc = func;
}
QRectF Square::boundingRect() const
{
return QRectF(-15, -15, 30, 30);
}
void Square::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
painter->setPen(Qt::black);
painter->setBrush(Qt::green);
painter->drawRect(-15, -15, 30, 30);
Q_UNUSED(option);
Q_UNUSED(widget);
}
void Square::slotTimer()
{
// 根据按钮触发情况移动正方形
if (GetAsyncKeyState('A'))
{
this->setX(this->x() - 2);
}
if (GetAsyncKeyState('D'))
{
this->setX(this->x() + 2);
}
if (GetAsyncKeyState('W'))
{
this->setY(this->y() - 2);
}
if (GetAsyncKeyState('S'))
{
this->setY(this->y() + 2);
}
// 调用回调函数传递正方形位置 类似于发信号给mainwindow 由mainwindow执行相应槽函数
m_callbackFunc(this->pos());
}
mainwindow.h部分代码
class MainWindow : public QWidget
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = Q_NULLPTR);
~MainWindow();
private:
Ui::MainWindow* ui;
QGraphicsScene* m_scene;
Square *m_square; // 声明正方形 传输回调
static QLineEdit *line1; // 声明一个静态QLineEdit, 执行回调
static QLineEdit *line2; // 声明一个静态QLineEdit, 执行回调
private:
// 声明一个回调函数
static void getPosition(QPointF point);
};
mainwindow.cpp部分代码
QLineEdit * MainWindow::line1;
QLineEdit * MainWindow::line2;
MainWindow::MainWindow(QWidget *parent)
: QWidget(parent)
{
ui = new Ui::MainWindow();
ui->setupUi(this);
// 初始化QLineEdit
line1 = new QLineEdit();
line2 = new QLineEdit();
// 把两个line 放进gridLayout
ui->gridLayout->addWidget(line1, 0, 1);
ui->gridLayout->addWidget(line2, 0, 2);
// 初始化图形场景
m_scene = new QGraphicsScene();
// 设置场景到 graphicsView
ui->graphicsView->setScene(m_scene);
m_scene->setSceneRect(0, 0, 300, 300);
m_square = new Square();
// 将getPosition设置回调 接收m_square传入的数据
m_square->setCallbackFunc(getPosition);
m_square->setPos(100, 100);
m_scene->addItem(m_square);
}
MainWindow::~MainWindow()
{
delete ui;
}
/**
* @fn MainWindow::getPosition
* @brief 回调函数接收正方形位置 写入两个lineEdit
* @param QPointF point
* @return void
*/
void MainWindow::getPosition(QPointF point)
{
line1->setText(QString::number(point.x()));
line2->setText(QString::number(point.y()));
}
原文地址:
https://evileg.com/ru/post/89/
还没有评论,来说两句吧...