如何最好地在Qt中存储动态创建的小部件的数据

时间:2019-02-10 22:18:40

标签: c++ qt lambda

我正在使用VC ++构建Qt应用程序,并且需要带有各种小部件的几种长格式。我试图动态分配这些小部件,以使添加新页面的过程更加简单。

为此,我将QStringList'key'和QVector 'vec'传递到保存该窗体的QDialog中。 key [i]的第一个字符保存窗口小部件类型,其余的保留标签。另一方面,每个vec [i]都需要保存用户更改的任何相应信息(来自动态创建的小部件)。

到目前为止,我已经在for循环中尝试了以下操作(每个循环都通过一个键):

char typeVal = key[i].toStdString()[0]; // widget type
key[i] = key[i].mid(1); // widget label

switch (typeVal)
{
    case 'e': // edit (lineedit)
    {
        QLineEdit *newEdit = new QLineEdit(page);
        connect(newEdit, &QLineEdit::textChanged, [&] {
            vec[vecIndex] = newEdit->text().toStdString(); });
        layout->addRow(key[i], newEdit);
        break;
    }
    // ...
}

但是,由于newEdit-> text(),这给了我一个“访问冲突读取位置”。这可能与我如何使用lambda函数槽有关,因为我对lambda声明了解不多。如果有此问题的解决方法,或者如果整个过程不必要地复杂,并且有更好的跟踪小部件数据的方法,我希望听到它。

1 个答案:

答案 0 :(得分:0)

您报告的访问冲突问题可能有以下原因。

您将信号连接到以下lambda函数:

[&] { vec[vecIndex] = newEdit->text().toStdString(); }

其中[&]部分告诉编译器通过引用捕获所有变量 ,也就是说,引用绑定到newEdit变量,该变量随后可在lambda函数中使用身体。但是,这不是您在这种情况下想要的。实际上,对newEdit的引用已绑定到一个变量,该变量在此绑定之后几乎立即被销毁(也就是说,在您的case语句范围的末尾),因此稍后尝试读取此变量(在插槽调用时)导致尝试从已破坏的变量中读取内容,因此相应的内存位置可能仅包含任何随机值,甚至根本无法读取。取消引用此类读取操作的结果会导致您报告细分冲突。

您想要的是newEdit指针的 value (它是QLineEdit pointer ,而不是对象本身),应该被lambda功能插槽保存以备后用。我假设这也适用于vecIndex,因为它看起来像您在问题中描述的某个循环变量,因此它会更改其值并可能在循环完成后销毁,但这取决于您应用程序的实际上下文。相反,vec变量可能需要通过引用进行捕获,因为您要修改“全局”矢量,而不是为lambda函数创建的本地副本。

假设,我们来以下lambda函数的声明:

[&vec, vecIndex, newEdit] { vec[vecIndex] = newEdit->text().toStdString(); }

表示以下事实:vec应该通过引用来捕获,而vecIndexnewEdit变量需要通过它们的值来捕获。

希望这会有所帮助。