Privacy policyContactsAbout siteOpinionsGitHubDonate
© EVILEG 2015-2018
Recommend hosting

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.



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

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
Last comments
Feb. 21, 2019, 12:51 p.m.
Евгений Легоцкой

Иногда CMake приходится перезапускать начисто, не обновляет кэш
Feb. 21, 2019, 12:29 p.m.

Я указал данные строки, т.к. без них у меня вылетала следующая ошибка: By not providing "FindQt5Core.cmake" in CMAKE_MODULE_PATH this project has asked CMake to find a package configurat...
Feb. 21, 2019, 12:08 p.m.

Вот атк выглядит мой проектник, посмотрите его. cmake_minimum_required(VERSION 3.6)project(projecttimer)set(CMAKE_CXX_STANDARD 11)set(CMAKE_AUTOMOC ON)set(CMAKE_AUTORCC ON)find_packa...
Feb. 21, 2019, 12:04 p.m.

Смотрите, если вы используете глобально для проекта -DCMAKE_PREFIX_PATH= то вам не надо уже указывать вот эти строкиset(Qt5Core_DIR "C:/Qt/5.12.1/mingw73_64/lib/cmake/Qt5Core")set(Qt5Gui_DIR...
Feb. 21, 2019, 11:54 a.m.

Даже не запускается. main.cpp у меня точно такой же, как в статье. CMakeLists.txt пришлось немного подправить (прикрепил ниже), т.к. не находились некоторые файлы. cmake_minimum_requi...
Now discuss on the forum
Feb. 21, 2019, 8:58 a.m.
Евгений Легоцкой

Ну у меня координаты передавались в зависимости от положения курсора мыши, а в вам по сути нужно будет аналогичным способом посылать даннные из полей ввода. Так что здесь скорее интерфес...
Feb. 20, 2019, 9:55 p.m.
Евгений Легоцкой

Не до конца понимаю сути вопроса, наверное, нужно увидеть программный код и попытку его применения, но к методам базового класса можно обращаться в наследованном классе через вызов по имени ба...
Feb. 20, 2019, 3:06 p.m.
Maciej Urmański

Yes, ok I have solution! Thank you for directing me about annotate.:) Solution is: users_in = User.objects.filter(joined_users__goal=goal, joined_users__joined=True)
Feb. 20, 2019, 2:40 p.m.
Евгений Легоцкой

Думаю, что ещё можно переопределить mouseReleaseEvent(QMouseEvent* event) у QTableView, который содержит модель и немного поиграться с индексом. Если это индекс, который соответству...
Feb. 20, 2019, 10:34 a.m.
Евгений Легоцкой

Да, так тоже можно. Единственный момент в том, что lupdate не всегда понимает, к какому контексту это дело относится, и может запихать в левый контекст. В небольшом проекте это не критич...
Join us in social networks

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