Qt/C++ - Lesson 026. Using CallBack function

callback c++, callback, callback функция, Qt callback, Qt урок

To transfer data in Qt uses signals and slots system, but this does not mean that you can not use the old proven method, namely the use CallBack functions. The fact that the use CallBack function is somewhat fast option than signals and slots. And also can be easier to use with regard to the fact that it is desirable to disconnect signals from the slots when an object sends a program signal is destroyed and is no longer used. This point is particularly relevant when one considers that, in C ++ there is no garbage collection, like Java or C# .

The principle of CallBack

The principle of CallBack

To use CallBack functions in a class that will have to return a result, you must declare a pointer to a function with the same signature as the function that will be used as a CallBack function. But to place the pointer on the function you want to use a class method to apply this pointer. That is, this method is passed a pointer to a function, which is set in the CallBack class pointer, which will return the result of its activities. At the same time in this class, this pointer is used as an ordinary function that will perform the action specified in the class from which this feature has been installed as a CallBack function in the current class.

For example, the class will be used, which draws a square on the graphic scene and Control keys W, A, S, D. When moving square should send data on their coordinates in the class that was created. That is, should call this class function as its CallBack function.

Project Structure

Project Structure

For a work function CallBack use project with the following structure:

  • mainwindow.h - The header of the main window;
  • mainwindow.cpp - source files of the main application window;
  • square.h - Header class file, the object of which is to use the CallBack function.
  • square.cpp - file source code of the class;


In the main window in the designer throws a graphic scene , and objects QLineEdit class, which will display the coordinates manually create and set in this window. Since the data objects must be declared as static. The same condition should apply for CallBack function. It must also be declared as static .


Also, in the header of the main window to declare the object class Square.


#include <QMainWindow>
#include <QGraphicsScene>
#include <QLineEdit>

#include <square.h>

namespace Ui {
class MainWindow;

class MainWindow : public QMainWindow

    explicit MainWindow(QWidget *parent = 0);

    Ui::MainWindow *ui;
    QGraphicsScene *scene;  
    Square *square;         // We declare the square, which will transmit the callback function
    static QLineEdit *line1;    // We declare a static QLineEdit, which will run the callback function
    static QLineEdit *line2;    // We declare a static QLineEdit, which will run the callback function

    // Declare a callback function
    static void getPosition(QPointF point);

#endif // MAINWINDOW_H


In addition to static objects QLineEdit their ads more necessary and implemented as functions in the source file, otherwise the compiler will announce an error. The fact that static objects necessarily need to be initialized.

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    ui(new Ui::MainWindow)

    // Инициализируем объекты QLineEdit
    line1 = new QLineEdit();
    line2 = new QLineEdit();

    // Устанавлвиваем их в gridLayout

    scene = new QGraphicsScene();       // Init graphics scene
    ui->graphicsView->setScene(scene);  // Set scene into the graphicsView
    square = new Square();              
    square->setCallbackFunc(getPosition);   // Set callback function into th square

    delete ui;

/* callback function receives a square position and places it in a position line1 and line2
 * */
void MainWindow::getPosition(QPointF point)

QLineEdit * MainWindow::line1;
QLineEdit * MainWindow::line2;


This class is inherited from QGraphicsItem and it is declared a pointer for the CallBack function and function for its installation. The function return values must be specified without fail.

#ifndef SQUARE_H
#define SQUARE_H

#include <QObject>
#include <QGraphicsItem>
#include <QPainter>
#include <QTimer>
#include <QPointF>

class Square : public QObject, public QGraphicsItem
    explicit Square(QObject *parent = 0);
    // Function for setting of callback function
    void setCallbackFunc(void (*func) (QPointF point));


public slots:

    QRectF boundingRect() const;
    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);

    QTimer *timer;  
    // Pointer to callback function
    void (*callbackFunc)(QPointF point);

private slots:
    void slotTimer();   

#endif // SQUARE_H


This example is similar in mechanics to the game, so no wonder the presence of the game timer. In the slot, connected to the signal from timer we implement movement square in the graphic scene and to transfer its coordinates in the CallBack function. And to check the status of target use functional buttons WinAPI .

#include "square.h"
#include <windows.h>

Square::Square(QObject *parent) :
    QObject(parent), QGraphicsItem()
    timer = new QTimer();
    connect(timer, &QTimer::timeout, this, &Square::slotTimer);



QRectF Square::boundingRect() const
    return QRectF(-15,-15,30,30);

void Square::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)


void Square::slotTimer()
    // Depending on the button pressed move the square around the stage
        this->setX(this->x() - 2);
        this->setX(this->x() + 2);
        this->setY(this->y() - 2);
        this->setY(this->y() + 2);
    // Call the callback function to transmit the coordinates of a square

void Square::setCallbackFunc(void (*func)(QPointF point))
    // Set the pointer to the callback function
    callbackFunc = func;


As a result, you should get the app, which made management a green square, and through the CallBack feature available data on its coordinates in the class of the main window.


10% refund of hotel reservation amount on Booking
10% refund of hotel reservation amount on Booking
We offer a link with a 10% return on the amount of the order when booking a hotel through Booking
Support the author Donate

Хорошо объяснено, но картинку я бы заменил =) А зачем создавать статические объекты?

QLineEdit * MainWindow::line1;

В данном конкретном случае сделать QLineEdit статическим является самым простым способом в принципе работать с этим объектом внутри статической функции. Если удалить static у QLineEdit, то метод getPosition выбросит ошибку, что невозможно чего-то там... точной формулировки не помню.

Недостаток статических методов в том, что они не будут работать с полями членами класса, если те не будут статическими. Есть конечно, ещё варианты несколько иначе получать id окна, с помощью API операционной системы, по нему кастовать полученный объект в MainWindow, а потом пройтись по child Объектам, найти нужный QLineEdit. Слишком геморно и вообще статья не о том.


У меня еще вопросы! 1.

"записали" координаты в указатель на функцию без реализации. 2.
void Square::setCallbackFunc(void (*func)(QPointF point))
    // Устанавливаем указатель на callback функцию
    func = callbackFunc ; // не логично ли такое присваивание?

1. Что значит без реализации? Это функция имеет реализацию. И реализацией это функции является метод:

void MainWindow::getPosition(QPointF point)

Да, это работать не будет, если не будет установлена соответствующая функция перед тем, как её использовать, но она в этом примере устанавливается:

square->setCallbackFunc(getPosition);   // Устанавливаем в квадрат callback функцию

2. Вообще никакой логики:

void Square::setCallbackFunc(void (*func)(QPointF point))
    // Устанавливаем указатель на callback функцию
    func = callbackFunc ; // не логично ли такое присваивание?

В корне неправильный подход. func - Это аргумент, который передаётся в класс для установки в качестве callback . А переменная callbackFunc - это просто указатель на функцию, в который нужно установить эту callback функцию, то есть аргумент func . Изначально там содержится nullptr , а если будет вызываться nullptr , то будет краш программы. А если Вы попытаетесь установить nullptr в указатель, который указывает на метод класса, который реализован, то будет краш программы.

Проще говоря, работать даже не будет. Это ещё с объектами такое можно будет сделать, когда например забрать указатель на какой-то объект класса извне. Да и то это в корне неправильный подход. Для такого существуют функции геттеры ( SomeClass* getSomeObject() , например )


А что означает

? Я просто меняю значение аргументов у указателя?

callbackFunc - это указатель на некую функцию, сигнатура которой указана в заголовочном файле класса Square

В качестве callbackFunc выступает метод void MainWindow::getPosition(QPointF point) . Посмотрите сигнатуру (сигнатура, то есть объявление идентично сигнатуре callbackFunc ) и реализацию этого метода. Вот что в нём реализовано то он и делает. А аргументы в функцию передаются, а что с ними уже происходит - это вопрос реализации.


I don’t understand in Mainwindow.cpp lines 40 + 41 what or how these lines work? They look like a declaration but they are in the implementation which doesnt make sense to me. Please explain:

  1. QLineEdit * MainWindow::line1;
  2. QLineEdit * MainWindow::line2;

There are static members of class. There in cpp file it isn`t declaration of these members, it`s implementation without assigning a value. Some value will be assigned to these members in constructor later.

That is what I thought however do not understand why it is necessary. I guess the format was new and unfamiliar to me. Found other examples online where the value was assigned to NULL. That worked as well.

It is especciality of workflow with static members.
And I think using of nullptr instead of NULL is better. Because of using of nullptr is modern standard of C++.


День добрый! Можешь выложить форму mainwindow.ui от урока? Заранее спасибо


Сам разборался, спасибо.


Only authorized users can post comments.
Please, Log in or Sign up
June 13, 2019, 7:01 p.m.
Taimoor Tanweer

C++ - Test 001. The first program and data types

  • Result:66points,
  • Rating points-1
June 13, 2019, 6:51 p.m.
Taimoor Tanweer

C++ - Test 002. Constants

  • Result:75points,
  • Rating points2
June 13, 2019, 12:30 p.m.
Ваня Мороз

C++ - Test 001. The first program and data types

  • Result:100points,
  • Rating points10
Last comments
June 17, 2019, 6:10 a.m.

Только по осям xAxis2, уAxis2 значения начинаются с 0. Почему-то xAxis2 и xAxis не синхронизированы по данным. Ну и QCustomPlot последний.
June 16, 2019, 8:21 p.m.
Евгений Легоцкой

Добрый день. Ну точно также добавляете ту же самую информацию на ось xAxis2, только добавляете другое форматирование customPlot->xAxis2->setDateTimeFormat("hh:mm"); если я ...
June 14, 2019, 1:56 p.m.
Egor Fomin

Спасибо за ваш ответ, у меня получилось реализовать это. Тем не менее появилась другая проблема, поэтому опять надеюсь на вашу помощь. Скажем, я уже выставил точки и они соеденены. Когда я нач...
June 13, 2019, 2:47 p.m.

Можно классу, который описывает точку, добавить сигнал, который подавать (emit), когда точка перемещается (переопределить mouseMoveEvent или mouseReleaseEvent). Так вот эти сигналы у каждой из...
June 13, 2019, 2:09 p.m.

Здравствайте! Подскажите, пожалуйста: customPlot->xAxis2->setTickLabels(true); //Здесь включается отображение данных на оси xAxis2. а можно как-то продублировать информацию cus...
Now discuss on the forum
June 20, 2019, 9:30 a.m.

Вернулся к этой задачке только-только, поэтому и не ответил ничего раньше.Как переопределить mouseReleaseEvent(QMouseEvent* event) у QTableView, если QTableView задан в ui? Или задавать QTabl...
June 19, 2019, 1:41 p.m.

Всем добрый день. При разборе XML файла наткнулся на тег вот такого плана: <TagName attribute1="value1" attribute2="value2" /> При попытке проверить на наличие такого элеме...
June 19, 2019, 12:55 p.m.

Скажите пожалуйста, как его в таком случае перемещать и удалять?
June 18, 2019, 7:50 p.m.

Большое спасибо! SDK заработал.К сожалению удалось продвинутся только на один шаг. При сборке чистого проекта NDK выдаёт следующие ошибки C:\Android\ndk-bundle/toolchains/arm-linux-andr...
June 18, 2019, 4:59 p.m.

Добрый день.В этом учебнике представлен код INSTALLED_APPS = ( ... 'rest_framework', 'snippets.apps.SnippetsConfig',) На строчке 'snippets.apps.SnippetsConf...
Looking for a Job?
25,000.00 руб. - 30,000.00 руб.
Разработчик Qt/C++
Barnaul, Altai Krai, Russia

For registered users on the site there is a minimum amount of advertising

Join us
© EVILEG 2015-2019
Recommend hosting TIMEWEB