微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Qt 中的信号/槽向量?

如何解决Qt 中的信号/槽向量?

首先介绍一下我为什么要这样做的背景:我有一个类,比如说 MasterClass,它是 QWidget 的子类,它创建多个新的 QObject 派生类对象,比如 SlaveClass,这会在运行时动态发生。使用 QThread 将新的 SlaveClass 移动到新的 movetoThread,因为它必须进行长时间运行的计算,而且我不希望我的 GUI 冻结。由于 SlaveClass 在不同的线程中,我调用 SlaveClass 中的任何方法的正确方法是使用 Qt 的信号/插槽机制和 Qt::QueuedConnection。 SlaveClass 有许多信号插槽,我想将它们连接到我的 MasterClass。我想要做的是在我的 MasterClass 中创建一个 signalsslotsQVector,以便我可以动态地添加删除它,{{1 }} 和 connect 这些到我的 SlaveClass 取决于 SlaveClass 是被创建还是销毁。

为了测试我的理论,我创建了一个 MasterClass 并尝试在其中创建 signalsslots 的向量并尝试连接 signalsslots 看看它是否有效:

第一次尝试[不起作用]:

大师班.h

disconnect

masterclass.cpp

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

这给出了 2 个错误

  1. E0304:没有重载函数“MasterClass::connect”的实例与参数列表匹配
  2. MSB4181:“QtRunWork”任务返回 false,但未记录错误

错误编号。上面 2 是因为我在 #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],&MasterClass::vSlt[1]); connect(this,&MasterClass::vSig[2],&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"; } 下声明了 QVector<std::function<void(int)>> vSig;,在 signals: 下声明了 QVector<std::function<void(int)>> vSlt;。一旦我将上述两个向量移到 private slots: 下,这个错误就会消失。

第二次尝试 [有效,但只是一种]:

大师班.h

private:

masterclass.cpp

.
.
.

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

这有效并打印: 78 69 60

这里有两点需要注意:

  1. 如果我删除 . . . 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,&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"; } 行,它不会打印任何内容
  2. 注意创建 connect(this,&MasterClass::slt_test);vSig 向量时参数的变化。从输出中,我可以看到正确的 vSlt调用,因为它将第二个 vSig 函数的参数加 1,并将第三个 vSig 函数的参数加 2。但是,它不会将第二个 vSig 函数的参数加 10 或第三个 vSlt 函数的参数加 20,这让我怀疑它是否调用了正确的 vSlt函数还是只是调用 vSlt 函数

有什么办法可以改进吗?

动态创建 slt_test() 对象时,我必须执行类似的操作才能连接到它的插槽 SlaveClass。可能吗?

附言我知道我可以使用 connect(MasterClasspointer,&MasterClass::vSig[id],SlaveClasspointer,&SlaveClass::slotName); 函数,但我想尽可能避免使用它。

解决方法

你可以有一个槽向量(一个 lambda 函数可以是一个槽),但你不能真正拥有一个信号向量。但是,您可以将信号连接到根据 ID 分派到正确插槽的东西:

// MasterClass.h
class MasterClass : public QObject {
// ... class stuff ...

signals:
  void masterSignal(int id);

private:
std::unordered_map<int,SlaveClass*> m_slaveMap;

}

// MasterClass.cpp ...
connect(this,&MasterClass::masterSignal,slavePtr,[](int id) { m_slaveMap[id]->slot(); });

另一种选择是过滤掉从插槽上带有错误 ID 的呼叫:

int slaveID = /*something*/
connect(masterPtr,[myID = slaveID,slavePtr] (int id) { if (myID == id) slavePtr->slot(); });

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。