【发布时间】:2021-05-25 15:13:29
【问题描述】:
首先了解一下我为什么要这样做的背景:我有一个类,比如 MasterClass,它是 QWidget 的子类,它创建了多个新的QObject 派生类对象,比如 SlaveClass,这在运行时动态发生。使用moveToThread 将新的SlaveClass 移动到新的QThread,因为它必须进行长时间运行的计算,并且我不希望我的GUI 冻结。由于 SlaveClass 在不同的线程中,我调用 SlaveClass 中的任何方法的正确方法是使用 Qt 的 Signal/Slot 机制以及Qt::QueuedConnection。 SlaveClass 有许多 signals 和 slots 我想连接到我的 MasterClass。我要做的是在我的 MasterClass 中创建 signals 和 slots 的 QVector,以便我可以动态添加和删除它以及 connect 和 @ 987654328@ 这些到我的 SlaveClass 取决于 SlaveClass 是被创建还是销毁。
为了验证我的理论,我创建了一个 MasterClass 并尝试在其中创建 signals 和 slots 的向量并尝试连接 signals 到 slots 看看它是否有效:
第一次尝试[不起作用]:
大师班.h
#include <QWidget>
#include <QVector>
#include <QDebug>
#include <functional>
Class MasterClass : public QWidget
{
Q_OBJECT
public:
MasterClass(QWidget *parent = nullptr);
~MasterClass();
signals:
void sig_test(int testID);
QVector<std::function<void(int)>> vSig;
private slots:
void slt_test(int testID);
QVector<std::function<void(int)>> vSlt;
};
masterclass.cpp
#include "masterclass.h"
MasterClass::MasterClass(QWidget *parent)
: QWidget(parent)
{
vSig << [this](int id) -> void{return this->sig_test(id); };
vSig << [this](int id) -> void{return this->sig_test(id); };
vSig << [this](int id) -> void{return this->sig_test(id); };
vSlt << [this](int id) -> void{return this->slt_test(id); };
vSlt << [this](int id) -> void{return this->slt_test(id); };
vSlt << [this](int id) -> void{return this->slt_test(id); };
connect(this, &MasterClass::vSig[0], this, &MasterClass::vSlt[0]);
connect(this, &MasterClass::vSig[1], this, &MasterClass::vSlt[1]);
connect(this, &MasterClass::vSig[2], this, &MasterClass::vSlt[2]);
emit vSig[0](78);
emit vSig[1](68);
emit vSig[2](58);
}
void MasterClass::slt_test(int testID)
{
qDebug() << "\n" << testID << "\n";
}
这给出了 2 个错误:
- E0304:没有重载函数“MasterClass::connect”的实例与参数列表匹配
- MSB4181:“QtRunWork”任务返回 false,但未记录错误。
错误编号。上面的2是因为我在signals:下声明QVector<std::function<void(int)>> vSig;,在private slots:下声明QVector<std::function<void(int)>> vSlt;。只要我将上述两个向量移动到private: 下,此错误就会消失。
第二次尝试[有效,但只是一种]:
大师班.h
.
.
.
signals:
void sig_test(int testID);
private slots:
void slt_test(int testID);
private:
QVector<std::function<void(int)>> vSig;
QVector<std::function<void(int)>> vSlt;
};
masterclass.cpp
.
.
.
vSig << [this](int id) -> void{return this->sig_test(id); };
vSig << [this](int id) -> void{return this->sig_test(id + 1); }; // Notice change in argument
vSig << [this](int id) -> void{return this->sig_test(id + 2); }; // Notice change in argument
vSlt << [this](int id) -> void{return this->slt_test(id); };
vSlt << [this](int id) -> void{return this->slt_test(id + 10); }; // Notice change in argument
vSlt << [this](int id) -> void{return this->slt_test(id + 20); }; // Notice change in argument
connect(this, &MasterClass::sig_test, this, &MasterClass::slt_test);
emit vSig[0](78);
emit vSig[1](68);
emit vSig[2](58);
}
void MasterClass::slt_test(int testID)
{
qDebug() << "\n" << testID << "\n";
}
这工作并打印: 78 69 60
这里有两点需要注意:
- 如果我删除
connect(this, &MasterClass::sig_test, this, &MasterClass::slt_test);行,它不会打印任何内容。 - 注意创建
vSig和vSlt向量时参数的变化。从输出中,我可以看到正确的vSig正在被调用,因为它将第二个vSig函数的参数加 1,并将第三个vSig函数的参数加 2。但是,它不会将 10 添加到第二个vSlt函数的参数或 20 到第三个vSlt函数的参数,这让我想知道它是在调用正确的vSlt函数还是只是在调用slt_test()函数?
有什么办法可以改善吗?
当动态创建SlaveClass 对象时,我必须做这样的事情来连接到它的插槽connect(MasterClassPointer, &MasterClass::vSig[id], SlaveClassPointer, &SlaveClass::slotName);。有可能吗?
附:我知道我可以使用QMetaObject::invokeMethod() 函数,但我想尽可能避免使用它。
【问题讨论】:
-
我认为它显然没有调用您的
vSlt插槽。为什么会呢?您永远不会将任何东西连接到这些插槽。 -
谢谢,我明白了,我也这么认为,但是为什么要将
vSig信号连接到slt_test插槽?我也从未建立过这种联系。只有sig_test连接到slt_test -
vSig只是一个函数向量。这些函数只需调用sig_test。由于sig_test连接到slt_test,调用vSig到达slt_test。 -
@JarMan 谢谢,有道理:)
标签: c++ multithreading qt signals-slots