weixin_41680380 2024-02-28 01:29 采纳率: 66.7%
浏览 50
已结题

qt中connect两个signal

最近遇到一个需求,由于以前有个项目使用了qt来实现(无界面),但是本人不熟悉C++ 只熟悉C,目前的需求是为了减小编译时的压力决定将qt全部用标准库代替,在翻代码的时候遇到了信号和槽,发现其中有一段是


connect(this,SIGNAL(signal_DataChange(QStringList)),m_pTripServer,SIGNAL(signal_DataChange(QStringList))); 

将两个信号做了连接。
问题1 两个信号连接之后起了什么作用?
问题2 假如是信号和槽函数做了连接,那槽函数肯定是要执行某个操作,但是现在变成了信号,请问这种情况会执行某个操作吗?
问题3 第一个signal_DataChange 是this中的一个函数,用于做触发来使用,不知道我理解的是不是正确,第二个signal_DataChange 是m_pTripServer中的一个函数吗?
问题4 如果是作为信号的传递,那信号传递到了什么地方?
希望能帮忙讲解一下connect 两个signal 和 普通connect signal和槽有什么区别,
下面附上部分代码


class TripServer : public QTcpServer
{
    Q_OBJECT
public:
    explicit TripServer(CPointNode *pPointNode_, int nCommonAddress, QObject *parent = 0);
    void timerEvent(QTimerEvent *);

signals:
    void signal_DataChange(QStringList strTagNameList);

public slots:
    void Slot_ClientSocketDisconnected();

private:
    void incomingConnection(int socketId);
private:
    QList<ClientSocket *> m_ClientSocketList;
    QMap<QString,ClientSocket *> m_ClientSocketMap;
public:
    void Set_Enable_AO_DO_IPAddressList(bool isEnDO,QList<QString> *pDO_List,bool isEnAO,QList<QString> *pAO_List);
    void Set_LinkLayeronfigInfo(_AAALinkLayerConfigInfo_New *pLinkLayeronfigInfo);
private:
    CPointNode *m_pPointNode;
    int m_nCommonAddress;
    _AAALinkLayerConfigInfo_New *m_pLinkLayeronfigInfo;
};

class CStart : public QObject
{
    Q_OBJECT
public:
    explicit CStart(const QString strFileName, QObject *parent = 0);
    void timerEvent(QTimerEvent *event);
    static CStart *s_pStart; 

signals:
    void signal_read_tag(QString strTagName_);
    void signal_DataChange(QStringList strNameList_);

public slots:
    void Slot_acceptError(QAbstractSocket::SocketError nSocketError);
    void InitPointMap(const QDomElement &DeviceListElement_);
    void InsertPoint(const QDomElement &PointElem_, int nPointType, int nDeviceAddress);
    DCTAG_API int slot_dc_tag_read ();
public:
    TripServer *m_pTripServer;
    QHostAddress m_hostAddress;

    QDomElement m_EleMainPort;
    CPointNode m_PointNode;

    TAG_DATA *m_pTags;

    void InitHostAddressList();
private:
    QDomElement m_ChannelElem;///< Channel节点
    int m_nCommonAddress; ///< 设备地址
};



bool CStart::SetInitTCP(const QDomElement &MainPort_)
{
    m_pTripServer = new TripServer(&m_PointNode,m_nCommonAddress,this);

    m_pTripServer->Set_Enable_AO_DO_IPAddressList(m_isEnable_DO_IP_Limit,&m_DO_IPAddress,m_isEnable_AO_IP_Limit,&m_AO_IPAddress);
    m_pTripServer->Set_LinkLayeronfigInfo(&m_LinkLayeronfigInfo);
    connect(this,SIGNAL(signal_DataChange(QStringList)),m_pTripServer,SIGNAL(signal_DataChange(QStringList)));
    connect(m_pTripServer,SIGNAL(acceptError(QAbstractSocket::SocketError)),this,SLOT(Slot_acceptError(QAbstractSocket::SocketError)));
    return TcpServerListen(MainPort_);
}

我参考了网上的教程,用标准库仿写了一个基本的信号槽函数,但是不支持connect两个signal,由于本人不熟悉c++,希望能得到帮助来针对两个signal连接的情况进行修改,下面附上我的信号槽demo


```c++

#include <iostream>
#include <string.h>
#include <vector>

using namespace std;
 
//槽类
template<class TParam>
class SlotBase
{
private:
    /* data */
public:
    virtual void slotFunction(TParam param) = 0;
    virtual ~SlotBase() = default;
};

template <class TRecver, class TParam>
class Slot : public SlotBase<TParam>
{
private:
    TRecver* m_pRecver;//定义一个接收者的指针,在构造中对其初始化
    void(TRecver::*m_func)(TParam param);//定义一个接收者类中的成员函数指针
public:
    Slot( TRecver* pObj, void(TRecver::*func)(TParam) )
    {
        this->m_pRecver = pObj;
        this->m_func = func;//使用类外的 接收者类的对象指针 与 接收者类中的成要换函数指针进行初始化。
    }
    void slotFunction(TParam param) override
    {
        (m_pRecver->*m_func)(param);//成员对象指针调用雷内的成员函数。
    }
};

//信号类
template <class TParam>
class Signal
{
private:
    vector<SlotBase<TParam>*> signal_vector;
public:
    template<class TRecver>
    void addSlot(TRecver* pObj, void (TRecver::*func)(TParam))
    {
        signal_vector.push_back(new Slot<TRecver, TParam>(pObj, func));
    }
    void operator()(TParam param)
    {
        for (SlotBase<TParam> * p : signal_vector )
        {
            p->slotFunction(param);
        }
    }
};

class Recver1
{
public:
    void func1(int param)
    {
        cout << "这是Recver1中的方法,参数为:"<< param << endl;
    }
};

class Recver2
{
public:
    void func2(int param)
    {
        cout << "这是Recver2中的方法,参数为:"<< param << endl;
    }
};

class SendObj
{
public:
    Signal<int> valueChanged;
public:
    void testSignal(int value)
    {
        valueChanged(value);
    }
};

#define connect(sender, signal, recver, method) (sender)->signal.addSlot(recver, method)
int main()
{
    Recver1 * r1 = new Recver1;
    Recver2 * r2 = new Recver2;

    SendObj * sd = new SendObj;
    connect(sd, valueChanged, r1, &Recver1::func1);
    connect(sd, valueChanged, r2, &Recver2::func2);
    sd->testSignal(10000);
    return 0 ;
}


```

  • 写回答

24条回答 默认 最新

  • 李美丽· 2024-02-29 21:45
    关注

    简单看了一下代码,如果要完全剔除qt的话需要的时间应该蛮多

    问题一:当signal_DataChange(QStringList)发射后会直接触发第二个信号m_pTripServer->signal_DataChange(QStringList)的发射,这意味着所有监听第二个信号的对象会接收到这个信号,并执行相关联的槽函数。
    问题二:两个信号进行了连接不会立即执行操作,但可以通过这种方式进行信号传递。
    问题三:是,第一个signal_DataChange是this的一个信号函数,第二个signal_DataChange是指m_pTripServer中的一个信号函数。
    问题四:signal_DataChange(QStringList)与signal_DataChange(QStringList) 相连接,如果signal_DataChange(QStringList)被触发,signal_DataChange(QStringList) 就会触发它的相应操作,除此之外,所有监听signal_DataChange(QStringList) 的都会收到信号

    关于你的问题:connect()函数实现的是信号与槽的关联,连接函数后可以采用多种重载方法,注意:只有QO bject类及其派生的类才能使用信号和槽的机制,所以你要去了解信号和槽机制的关系。static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType = Qt::AutoConnection);第一个参数sender为发送对象;第二个参数为发送对象里面的一个信号;第三个参数为接收对象;第四个参数为接收对象里面的槽函数。一般我们使用发送者触发信号,然后执行接收者的槽函数。接着就可以定义槽函数的内容,就实现了用信号触发执行槽函数的功能,两者的区别在于连接的对象不同,一个是信号和槽函数的连接,另一个是信号的连接。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(23条)

报告相同问题?

问题事件

  • 系统已结题 3月8日
  • 已采纳回答 2月29日
  • 创建了问题 2月28日

悬赏问题

  • ¥20 关于游戏c++语言代码问题
  • ¥15 如何制作永久二维码,最好是微信也可以扫开的。(相关搜索:管理系统)
  • ¥15 delphi indy cookie 有效期
  • ¥15 labelme打不开怎么办
  • ¥35 按照图片上的两个任务要求,用keil5写出运行代码,并在proteus上仿真成功,🙏
  • ¥15 免费的电脑视频剪辑类软件如何盈利
  • ¥30 MPI读入tif文件并将文件路径分配给各进程时遇到问题
  • ¥15 pycharm中导入模块出错
  • ¥20 Ros2 moveit2 Windows环境配置,有偿,价格可商议。
  • ¥15 有关“完美的代价”问题的代码漏洞