Qt QFormLayout::addRow添加新行不显示、addWidget失效问题
问题根因
控件无法显示、后续布局接口失效的核心原因是Qt控件生命周期管理错误:
- 你在
for循环内部定义的QLineEdit fullNameEdit、QLineEdit shortNameEdit是栈上分配的局部变量,生命周期仅存在于单次循环迭代的作用域内 - 单次循环结束后这两个输入框会立刻被析构销毁,你传给
formLayout->addRow()的是已经失效的野指针,布局拿不到有效控件自然不会渲染任何可见内容 - 失效的野指针会破坏布局内部的对象树结构,直接导致后续调用
addWidget()等接口也无法正常添加控件
修复方案
将需要添加到布局的QLineEdit改为堆上分配(使用new创建),指定父对象即可,Qt的对象树机制会自动管理内存,不需要手动释放。
修复后的循环代码如下:
//Correctly add QLineEdits to the FormLayout for (auto names : boost::combine(keglerFullName, keglerShortName)) { // 改为new创建堆上对象,指定父窗口为keglerTab QLineEdit* fullNameEdit = new QLineEdit(ui.keglerTab); QLineEdit* shortNameEdit = new QLineEdit(ui.keglerTab); QJsonValue fullNameValue, shortNameValue; boost::tie(fullNameValue, shortNameValue) = names; if (fullNameValue.isString()) { fullNameEdit->setText(fullNameValue.toString()); fullNameEdit->setObjectName("fullName"); fullNameEdit->setMinimumWidth(width); } if (shortNameValue.isString()) { shortNameEdit->setText(shortNameValue.toString()); shortNameEdit->setMaximumWidth(width); shortNameEdit->setObjectName("shortName"); } formLayout->addRow(fullNameEdit, shortNameEdit); }
额外注意事项
- 所有需要长期显示的QWidget子类控件都必须在堆上创建,不要将栈上局部控件的指针传给布局,Qt布局不会延长栈对象的生命周期
- 如果后续需要读取这些输入框的内容,可以给每个输入框设置唯一的objectName,通过父控件的
findChild<QLineEdit>()方法查找,也可以提前用QList等容器存储所有输入框的指针方便后续访问
内容的提问来源于stack exchange,提问作者Bugsia
相关产品推荐
相关产品推荐

