Home > database >  QT/C Call function of a widget using a slot
QT/C Call function of a widget using a slot

Time:08-10

Consider following main.cpp (the only file of the whole Qt-project):

#include <QApplication>
#include <QWidget>
#include <QPushButton>
#include <QVBoxLayout>
#include <QLabel>
#include <QObject>
#pragma once

class collectedFunctions : public QObject
{
    Q_OBJECT

public:
    collectedFunctions(QObject* parent = 0) {};
    ~collectedFunctions() {};

public slots:
    void setFunc() {
        //Calculate 2 2 and change text of the label accordingly
    }
};

#include "main.moc"

int main(int argc, char* argv[]) {

    QApplication app(argc, argv);

    QWidget window;
    window.resize(200, 200);
    window.setWindowTitle("Test-GUI");
    QVBoxLayout layout(&window);

    QPushButton button(&window);
    button.setText("Test");
    button.show();
    
    QLabel *label = new QLabel(&window);
    label->setText("Hello");

    collectedFunctions testingFuncs;

    QObject::connect(&button, &QPushButton::clicked, &testingFuncs, &collectedFunctions::setFunc);
    
    layout.addWidget(&button);
    layout.addWidget(label);
    
    window.show();
    return app.exec();
}

My goal with this code is to create a slot that runs a function which the programmer defines (similar to the pyqt-implementation of the signals and slots system). The code above successfully compiles, not throwing any errors and so far meeting my expectations. Yet as soon I want to manipulate a widget (which in this case is the label), the setfunc-slot does not find the defined label. How can I manipulate a widget using this slot (e.g. using setText() at a label or addItems() at a combobox) or generally have them being recognized in the slot.

Update: Thanks to the solution of this question, I figured that I could simply use a lambda instead of the Q_OBJECT makro, so I removed the header-code and then changed the connect from the Button to following:

QObject::connect(&button, &QPushButton::clicked, [&label](){
int num = 2   2;
string text = "2 2 = ";
text  = std::to_string(num);
QString qtext = QString::fromStdString(text);
label->setText(qtext); });

CodePudding user response:

you shouldn't use the Q_OBJECT macro in main.cpp.

The Q_OBJECT macro must appear in the private section of a class definition that declares its own signals and slots or that uses other services provided by Qt's meta-object system.

The moc tool reads a C header file. If it finds one or more class declarations that contain the Q_OBJECT macro, it produces a C source file containing the meta-object code for those classes. Among other things, meta-object code is required for the signals and slots mechanism, the run-time type information, and the dynamic property system.

The C source file generated by moc must be compiled and linked with the implementation of the class.

When you have your class defined in .cpp file instead of .h file moc fails to process it properly.

you need a separate file for class:

in collectedfunctions.h

#pragma once
#include <QObject>

class collectedFunctions: public QObject
{
    Q_OBJECT

public:
    collectedFunctions(QObject *parent = 0);

    ~collectedFunctions();

public slots:
    void  setFunc();
};

and in collectedfunctions.cpp

#include "collectedfunctions.h"
#include <QDebug>

collectedFunctions::collectedFunctions(QObject *parent)
{
}

collectedFunctions::~collectedFunctions()
{
}

void  collectedFunctions::setFunc()
{
    qDebug() << "2 2 = " << 2   2;
}

and in your main.cpp

 #include <QApplication>
 #include <QWidget>
 #include <QPushButton>
 #include <QVBoxLayout>
 #include <QLabel>

#include "collectedfunctions.h"

int  main(int argc, char *argv[])
{
    QApplication  app(argc, argv);
    QWidget       window;

    window.resize(200, 200);
    window.setWindowTitle("Test-GUI");
    QVBoxLayout  layout(&window);
    QPushButton  button(&window);
    button.setText("Test");
    button.show();

    QLabel *label = new QLabel(&window);
    label->setText("Hello");

    collectedFunctions  testingFuncs;

    QObject::connect(&button, &QPushButton::clicked, &testingFuncs, &collectedFunctions::setFunc);

    layout.addWidget(&button);
    layout.addWidget(label);

    window.show();

    return app.exec();
}

don't forget to add QT =core gui widgets in your .pro file.

Result:

enter image description here

If you want to change QLabel Text :

in collectedfunctions.h

#pragma once
#include <QObject>

class collectedFunctions: public QObject
{
    Q_OBJECT

public:
    explicit collectedFunctions(QObject *parent = 0);

    ~collectedFunctions();

signals:
    void  updateLable(int num);

public slots:
    void  setFunc();

private:
    int  num = 0;
};

and in collectedfunctions.cpp

#include "collectedfunctions.h"
#include <QDebug>

collectedFunctions::collectedFunctions(QObject *parent)
{
}

collectedFunctions::~collectedFunctions()
{
}

void  collectedFunctions::setFunc()
{
    qDebug() << "2 2 = " << 2   2;

    num  ;
    emit  updateLable(num);
}

and in your main.cpp

#include <QApplication>
#include <QWidget>
#include <QPushButton>
#include <QVBoxLayout>
#include <QLabel>

#include "collectedfunctions.h"

int  main(int argc, char *argv[])
{
    QApplication  app(argc, argv);
    QWidget       window;

    window.resize(200, 200);
    window.setWindowTitle("Test-GUI");
    QVBoxLayout  layout(&window);
    QPushButton  button(&window);
    button.setText("Test");
    button.show();

    QLabel *label = new QLabel(&window);
    label->setText("Hello");

    collectedFunctions  testingFuncs;

    QObject::connect(&button, &QPushButton::clicked, &testingFuncs, &collectedFunctions::setFunc);

    QObject::connect(&testingFuncs, &collectedFunctions::updateLable, [&label](int num)
    {
        qDebug() << "Number = " << num;
        label->setText(QString::number(num));
    });

    layout.addWidget(&button);
    layout.addWidget(label);

    window.show();

    return app.exec();
}

you can see:

enter image description here

  •  Tags:  
  • c qt
  • Related