Qt Creator跨类信号槽实现咨询(继承QSerialPort场景)
Qt跨类信号槽问题解答
这种实现方式完全可行,你代码里connect参数位置的???直接填u2c就能完成连接,不过你现有代码有几个必须修正的问题,否则会出现信号无法触发、连接失败的情况。
核心逻辑说明
- Qt信号槽基于QObject元对象系统实现,只要子类继承自QObject派生类,就会完整继承基类的所有信号、槽方法,不需要额外实例化基类对象。你的
USB2CAN_driver继承自QSerialPort,实例化出的u2c对象本身就持有基类QIODevice定义的readyRead()信号,直接将该实例作为信号源传入connect即可。 - 你当前代码第一个致命问题:在
usb2can_driver.h中自定义了同名的void readyRead()信号,这会覆盖基类的同名信号,但QSerialPort内部有数据可读时触发的是基类自带的readyRead(),你自己重写的同名信号不会被自动触发,直接删掉这段自定义信号的代码即可,直接用继承来的信号就行。 - 第二个无效代码:
canview.h中写的friend void USB2CAN_driver::readyRead();完全多余,Qt的信号默认是public访问权限,不需要友元声明就能跨类连接,直接删掉即可。 - 第三个签名不匹配问题:你写的
read_u2c()、read_USB2CAN()槽函数返回值定义为QByteArray,Qt槽函数的返回值在信号触发调用时无法被接收,属于无效定义,部分Qt版本会因为槽函数签名和信号不匹配导致连接失败,直接把返回值改成void即可。
关键位置修正代码
- 修改
usb2can_driver.h,删除自定义的readyRead信号:// 删除以下两行冗余的自定义信号代码 // public: signals: // void readyRead(); - 修改
canview.h,删除无效友元声明,修正槽函数返回值:// 删除无效的友元声明 // private: signals: // friend void USB2CAN_driver::readyRead(); // 修正槽函数返回值为void private slots: void on_connectPort_released(); void on_pushButton_released(); void read_u2c(); void timerSubrutine(); - 修改
canview.cpp中的连接代码,替换???为u2c,同时修正read_u2c()的实现逻辑(你原来连续三次调用readAll(),第一次调用就会把缓冲区数据读空,后面两次读到的都是空内容):// connect位置修正 qDebug() << "Connect rx task, status: " << connect(u2c,SIGNAL(readyRead()),this,SLOT(read_u2c())); // read_u2c实现修正 void CANview::read_u2c(){ QByteArray recvData = u2c->readAll(); qDebug() << "RX:" << recvData; ui->RX_textBrowser_2->setPlainText(recvData); }
其他冗余代码提示
connectToPort函数中重复调用了两次setPortName,删掉一次即可。- 函数中
new QTimer时没有指定父对象,改成new QTimer(this),避免内存泄漏。 - 测试阶段残留的
QSignalSpy相关代码在正式版本中可以直接删除,没有实际业务作用。
内容的提问来源于stack exchange,提问作者BobEr
相关产品推荐
相关产品推荐

