QT/C++使用插槽调用控件的函数

fkaflof6  于 2023-03-20  发布在  其他
关注(0)|答案(2)|浏览(170)

考虑以下main.cpp(整个Qt项目的唯一文件):

#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();
}

我编写这段代码的目的是创建一个运行程序员定义的函数的插槽(类似于信号和插槽系统的pyqt实现)。
上面的代码成功编译,没有抛出任何错误,到目前为止满足了我的期望。
然而,只要我想操作一个小部件(在本例中是标签),setfunc-slot就找不到定义的标签。
我如何使用这个槽来操作一个小部件(例如,在标签上使用setText()或在组合框上使用addItems()),或者通常在槽中识别它们?

**更新:**由于这个问题的解决,我认为我可以简单地使用lambda来代替Q_OBJECT makro,所以我删除了头代码,然后将连接从Button更改为以下内容:

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); 
                 });
mtb9vblg

mtb9vblg1#

你不应该在main.cpp中使用Q_OBJECT宏.
Q_OBJECT宏必须出现在类定义的私有部分,该类定义声明自己的信号和插槽,或者使用Qt的元对象系统提供的其他服务。
moc工具读取C++头文件。如果它发现一个或多个类声明包含Q_OBJECT宏**,它将生成一个包含这些类的元对象代码的C源文件。其中,信号和插槽机制、运行时类型信息和动态属性系统都需要元对象代码。
moc生成的C
源文件必须编译并与类的实现链接。
当您在.cpp文件而不是.h文件中定义类时,moc无法正确处理它。

您需要一个单独的类文件:
在收集的函数中。h

#pragma once
#include <QObject>

class collectedFunctions: public QObject
{
    Q_OBJECT

public:
    collectedFunctions(QObject *parent = 0);

    ~collectedFunctions();

public slots:
    void  setFunc();
};

以及收集的函数.cpp中的函数

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

collectedFunctions::collectedFunctions(QObject *parent)
{
}

collectedFunctions::~collectedFunctions()
{
}

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

以及主.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();
}

别忘了在.pro文件中添加QT +=core gui widgets

结果:

如果要更改QLabel文本:

在收集的函数中。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;
};

以及收集的函数.cpp中的函数

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

collectedFunctions::collectedFunctions(QObject *parent)
{
}

collectedFunctions::~collectedFunctions()
{
}

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

    num++;
    emit  updateLable(num);
}

以及主.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();
}

您可以看到:

xhv8bpkk

xhv8bpkk2#

来自Qt文档QObject::connect()

template〈类型名指向成员函数的指针,类型名函数〉QMetaObject::连接QObject::连接(常量QObject * 发送方,指向成员函数的指针信号,函数的函数)

此函数重载connect()。
创建从发送者对象中的信号到函数的连接,并返回连接的句柄
信号必须是在标头中声明为信号的函数。槽函数可以是可连接到信号的任何函数或函子。如果给定信号的参数至少与槽函数的参数一样多,则槽函数可连接到该信号。信号和槽中对应参数的类型之间必须存在隐式转换。
示例:

void someFunction();
QPushButton *button = new QPushButton;
QObject::connect(button, &QPushButton::clicked, someFunction);

相关问题