Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Communicate with non-member function



  • I am wondering how can i do this and its` logic.

    I have a QMainWindow and a function but this function is not a member. Such as:

    //non-member function (related with an external library)
    void Callback(input params)
    {
        // This function generates data every second
        // I  want to use these data when painting over widgets
    }
    
    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
        QTimer::singleShot(1000, this, SLOT(showFullScreen()));
    
        /*
        *
        * QGraphics, QPaint functions for painting on widgets in the MainWindow
        *
        */
    }
    

    How can I send these generated location(x,y,w,h) data to UI thread and use them for painting/drawing? Do i need to create a new thread? Please explain me, how to do this in most appropriate way? Thanks in advance :)



  • @R_Irudezu
    Not sure what you mean! What about:

    1. Run the external library stuff in its own thread. This is to allow the Qt UI to remain "responsive" if the external thread is away computing stuff for a periods.

    2. When the external calls your Callback() function, have that emit() a signal to say new data has arrived, and pass the data on as necessary.

    3. Have your Qt UI code connect that signal to a slot, and in the slot use the parameters to do whatever plotting in Qt.



  • This post is deleted!


  • It might not be that difficult.. Just sending data from global function to UI Window.

    void generateData(params)
    {
        // the data generated here needs to be passed to UI window
    }
    

    UI section:

    Use these data as QPainter function parameters. That's all but how to do..


  • Qt Champions 2017

    Assuming that generateData(..) function is written by you. Add new class in Called DataGenerator inherit from QObject. Create the DataGenerator object as global object. This object should be accessible from both your callback() and MainWIndow class.

    Define the method acceptData(x,y), in DataGenerator which is called whenever callback is called.
    Define the signal in DataGenerator. Send this signal from acceptData(..) method.
    Catch this signal in in your mainWindow.

    In summary you have QObject class which acts as intermediately between your call back and MainWindow.



  • So i did like:
    (mainwindow.h)

    #include <QMainWindow>
    #include <QObject>
    
    namespace Ui {
    class MainWindow;
    class dataSender; // which you mean DataGenerator Class
    }
    
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    
    public:
        explicit MainWindow(QWidget *parent = nullptr);
        ~MainWindow();
    
    private:
        Ui::MainWindow *ui;
    
    };
    
    class dataSender: public QObject
    {
        Q_OBJECT
    
    public:
    
        int acceptData(int *getx, int *gety)
        {
            int acceptedData = *get;
            return acceptedData;
        }
    
        dataSender(QObject * parent) : QObject(parent)
        {
            dataSender* parent= qobject_cast<dataSender*>(parent);
    
            // i don't know how to use here @dheerendra 
            if (parent)
                QObject::connect(parent, SIGNAL(acceptDataSignal()), this, SIGNAL(acceptDataSignal()));
           
        }
    
    signals:
        
        void acceptDataSignal();
    
    };
    
    #endif // MAINWINDOW_H
    
    

    (mainwindow.cpp)

    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    
    // here my global callback function
    // i mean yes your assume is right, i am gonna write this function and it will generate data
    void callBack(int *x, int *y)
    {
        /* this values will be change every second, i just want to see them change in 
           UI QLabel or TextEdit widget 
        */
    
        x += 5;
        y += 10;
    }
    
    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
    
        // here data must be shown in label and i want to see them change every second
        ui->testLabel->text = "x is" + x + "and y is " + y;
    }
    
    MainWindow::~MainWindow()
    {
        delete ui;
    }
    
    

    so what now, i really do not know how to use signal and slot in this case.


  • Qt Champions 2017

    See the following program and use it.

    class GenerateData : public QObject
    {
    Q_OBJECT
    public:
    explicit GenerateData(QObject *parent = nullptr);
    void display();
    signals:
    void sendData(int x, int y);
    public slots:
    };

    #include "GenerateData.h"

    GenerateData::GenerateData(QObject *parent) : QObject(parent)
    {

    }

    void GenerateData::display()
    {
    qDebug() << Q_FUNC_INFO << endl;
    emit sendData(10,20);
    }
    class MyWidget : public QWidget
    {
    Q_OBJECT

    public:
    explicit MyWidget(QWidget *parent = 0);
    ~MyWidget();
    void display();
    void setGenerator(GenerateData *d1);

    public slots :
    void plotData(int x, int y);

    private:
    Ui::MyWidget *ui;
    GenerateData *dg;
    };

    MyWidget::MyWidget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::MyWidget)
    {
    ui->setupUi(this);
    }

    MyWidget::~MyWidget()
    {
    delete ui;
    }
    void MyWidget::setGenerator(GenerateData *d1)
    {
    this->dg = d1;
    connect(this->dg,SIGNAL(sendData(int,int)),this,SLOT(plotData(int,int)));
    }

    void MyWidget::plotData(int x, int y)
    {
    qDebug() << " X=" << y << " Y =" << y <<endl;
    }

    ========main.cpp============
    #include "MyWidget.h"
    #include "GenerateData.h"
    #include <QApplication>

    GenerateData d;

    void callme(MyWidget *w) {
    std::cout << " Welcome to all" << endl;
    d.display();
    }

    int main(int argc, char *argv[])
    {
    QApplication a(argc, argv);
    MyWidget w;
    w.show();
    w.setGenerator(&d);
    callme(&w);

    return a.exec();
    

    }



  • @dheerendra this code works thanks but when i use in the MainWindow's constructor or in a button slot such as:

    void MainWindow::on_pushButton_clicked()
    {
        MainWindow w;
        w.setGenerator(&d);
        callme(&w);
    }
    

    when i run it, it gives SIGSEGV error. How can i use this object in MainWindow.cpp not in main.cpp


  • Qt Champions 2017

    You are creating the stack object and hence crashes. Create the dynamic object like the following.

    MainWindow *w = new MainWindow;
    w->setGenerator(&d);
    callme(w);



  • @dheerendra Thank you for all your help sir!


  • Qt Champions 2017

    Move this issue to solved state, if it already solved the problem.



  • @dheerendra I already did.


  • Qt Champions 2017

    MainWindow *w = new MainWindow;

    Make the variable w as member variable. Then delete it when you don't require the object any more.


Log in to reply