【问题标题】:Qt6 Connect Signal to Lambda FunctionQt6 将信号连接到 Lambda 函数
【发布时间】:2022-01-08 14:47:22
【问题描述】:

我正在使用DataRouter 类来处理与QSerialPort 的通信(然后在其他地方传达结果)。连接的设备每秒左右发送一个状态包,我想在不轮询设备的情况下读取它。我尝试直接使用QSerialPortwaitForReadyRead函数,但是无论我设置等待时间多长,它总是超时。看着 herehere 我看到信号可以连接到 Lambda 函数。现在我正在尝试将QSerialPortreadyRead 信号连接到调用我的on_dataRecieved 函数的Lambda,但我收到错误C2665:"QObject::connect: none of the 3 overloads could convert all of the argument types。以下是我所拥有的示例:

DataRouter.h

template<class SerialPort>
class DataRouter
{
public:
    DataRouter ();
private slots:
    on_dataRecieved();
private:
    shared_ptr<SerialPort> m_port;
};

DataRouter.cpp

template<class SerialPort>
DataRouter<SerialPort>::DataRouter()
{
    m_port = std::make_shared<SerialPort>()
    QObject::connect(m_port, &QSerialPort::readyRead, this, [=](){this->on_dataRecieved();})
}

template<class SerialPort>
void DataRouter<SerialPort>::on_dataRecieved()
{
 //Do stuff
}

【问题讨论】:

    标签: c++ c++17 qt6


    【解决方案1】:

    如果您的“目标”不是 QObject,您需要使用以下 connect 重载。问题是,您试图使用非 QObject 作为“上下文”来确定连接的生命周期,这是不可能的。为了减轻它,您需要在 DataRouter 被破坏时以某种方式释放连接;一种方法是存储 connect() 将返回的内容并稍后调用 disconnect

    关于来自智能指针的信号,你有没有试过这个: connect(m_port-&gt;get(), &amp;QSerialPort::readyRead, &amp;DataRouter::on_dataRecieved);

    【讨论】:

    • 我刚刚尝试了您的建议,不幸的是,它给了我与之前相同的错误“C2665 ... 4 个重载都没有...”
    • 如果您尝试将 on_dataRecieved 包装成 lambda 会怎样?
    【解决方案2】:

    您的m_port 不是QSerialPort 类的实体,这就是为什么您没有可以从中发出的QSerialPort::readyReadtemplate&lt;class SerialPort&gt; 不做什么,它只是模板化参数的名称。 你可能想要这样的东西:

    DataRouter.h

    class DataRouter : QObject
    {
    public:
        DataRouter ();
    private slots:
        on_dataRecieved();
    private:
        QSerialPort* m_port;
    };
    

    DataRouter.cpp

    DataRouter::DataRouter()
    {
        m_port = new QSerialPort(this);
        connect(m_port, &QSerialPort::readyRead, this, &DataRouter::on_dataRecieved);
        // or connect(m_port, &QSerialPort::readyRead, this, [this](){this->on_dataRecieved();});
    }
    
    void DataRouter::on_dataRecieved()
    {
     //Do stuff
    }
    

    您不必将 Qt 类包装在智能指针中,因为您为它们提供了父类。当父级被破坏时释放内存。

    【讨论】:

    • 您说得对,需要将 m_port 从模板类型更改为 QSerialPortDataRouter 类不是 QObject 所固有的,因此它不能是 new QSerialPort (this) 的构造函数中的父级。 on_dataRecieved 方法是否需要属于继承自 QObject 的类才能成为插槽?
    • 你是对的,关于 DataRouter 不能成为父母的事实,我的错。至于你的问题,我认为不需要,但是,我可能弄错了。您可以使用 lambda 编写连接部分,就像您在示例中所做的那样: connect(m_port, &QSerialPort::readyRead, this, [this](){this->on_dataRecieved();});这并不要求 DataRouter 是 QObject。
    • 我已尝试按照您的建议在连接中使用 lambda,但它给了我与以前相同的错误。虽然现在建议说“没有从DataRouter* to``` const QObject*``` 用于第三个参数的已知转换”。
    • 我已经更新了我的答案,现在 DataRouter 继承自 QObject,您可以将其用作父级并使用连接。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-09-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-15
    • 1970-01-01
    相关资源
    最近更新 更多