Qt信号槽连接报错No such slot FileInput::writeToFile()求助
Qt 信号槽报错:No such slot FileInput::writeToFile() 修复
运行报错信息
qt.core.qobject.connect: QObject::connect: No such slot FileInput::writeToFile()
问题原因
一共3个核心问题导致报错和后续潜在崩溃:
- 信号槽连接语法使用错误
你使用的是Qt4老式字符串匹配的SIGNAL/SLOT连接语法,这种语法要求SLOT()宏内只能写函数的类型签名,不能传入实际参数。你写的SLOT(writeToFile(lem))会被Qt解析为查找无参的writeToFile()槽函数,但你实际定义的槽是void writeToFile(QObject *obj)带参数版本,签名不匹配,直接触发找不到槽的错误。 - 传参对象生命周期错误
你在set_GUI()函数内定义的Product lem = Product();是栈上局部变量,set_GUI()执行完就会被自动销毁,就算连接写对,后续点击按钮触发函数时访问这个已经销毁的对象会直接导致程序崩溃。 - 老式语法无编译期检查
Qt4的字符串式连接不会在编译阶段校验函数是否存在、参数是否匹配,所有错误只会在程序运行时抛出警告,排查成本很高。
修复步骤
- 修改
fileinput.h,把Product实例改为类成员,保证生命周期覆盖按钮点击的时机:
// 在FileInput类的private成员区新增Product成员指针 private: QPushButton *xx; QPushButton *pp; Product *lem;
- 修改
fileinput.cpp(你文档里笔误写成了filminput.cpp)的set_GUI()函数,替换为Qt5推荐的新式信号槽连接+lambda传参,这种写法支持编译期检查,也可以自由传入自定义参数。另外你本身FileInput就是QWidget子类,不需要额外new一个局部QWidget作为窗口,直接用当前对象即可:
void FileInput::set_GUI() { resize(250,250); setWindowTitle("Q Meta Nonsence"); // 初始化成员变量lem,指定父对象自动回收内存 lem = new Product(this); lem->setName("PHIL"); lem->setPrice(16.45); xx = new QPushButton("Exit"); pp = new QPushButton("Print"); QVBoxLayout *ll = new QVBoxLayout; ll->addWidget(xx); ll->addWidget(pp); ll->setSpacing(25); setLayout(ll); show(); // Exit按钮改用新式连接,编译期做校验 connect(xx, &QPushButton::clicked, this, &QWidget::close); // Print按钮用lambda捕获this指针,调用带参数的writeToFile connect(pp, &QPushButton::clicked, this, [this](){ QDout(); // 测试函数直接在这里调用即可 writeToFile(lem); }); }
- 修复
writeToFile()里的逻辑bug:文件打开失败时不需要调用close(),直接返回即可:
void FileInput::writeToFile(QObject *obj) { QFile file("C:/Users/marti/Documents/Qt/QM/data.txt"); if(!file.open(QFile::WriteOnly|QFile::Text|QFile::Append)) { qDebug() << "File open failed, error:" << file.errorString(); return; } QTextStream toFile(&file); const QMetaObject *mo = obj->metaObject(); for(int i=mo->propertyOffset(); i<mo->propertyCount(); i++) { const QMetaProperty prop = mo->property(i); QString name = prop.name(); QVariant value = prop.read(obj); QString valStr = value.toString(); toFile << name << ": " << valStr << "\n"; } file.close(); }
补充说明
新式信号槽写法可以直接连接到槽函数地址,比如要单独测试QDout(),直接写connect(pp, &QPushButton::clicked, this, &FileInput::QDout);即可正常生效,不会出现找不到槽的问题。
内容的提问来源于stack exchange,提问作者Martin Sieburg
相关产品推荐
相关产品推荐

