Как лучше хранить данные динамически создаваемых виджетов в Qt - PullRequest
0 голосов
/ 11 февраля 2019

Я создаю приложение Qt с VC ++, и мне нужно несколько длинных форм с различными виджетами.Я пытаюсь выделить эти виджеты динамически, чтобы сделать процесс добавления новых страниц намного проще.

Для этого я передаю QStringList 'key' и QVector 'vec' в QDialog, который содержит форму.Первый символ ключа [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 ().Это может быть проблемой с тем, как я использую слот лямбда-функции, так как я мало что знаю о лямбда-объявлениях.Если для этого есть исправление или если весь процесс излишне запутан и есть лучший способ отслеживания данных виджета, я бы хотел это услышать.

1 Ответ

0 голосов
/ 11 февраля 2019

Проблема нарушения доступа, о которой вы сообщаете, вероятно, имеет следующую причину.

Вы подключаете свой сигнал к следующей лямбда-функции:

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

, где [&] part указывает компилятору захватить все переменные по ссылке , то есть ссылка связывается с переменной newEdit, которая затем доступна в теле лямбда-функции.Это, однако, не то, что вы хотите в этой ситуации.Ссылка на newEdit фактически привязана к переменной, которая уничтожается почти сразу после этой привязки (то есть в конце области действия оператора case), поэтому пытаюсь прочитать эту переменную позже (при вызове слота).время) приводит к попытке чтения чего-либо из уничтоженной переменной, поэтому соответствующая ячейка памяти может содержать любое случайное значение или вообще быть недоступной для чтения.Разыменование результата такой операции чтения приводит к нарушению сегментации, о котором вы сообщаете.

Здесь вы хотите указать значение из newEdit (это указатель to QLineEdit, а не сам объект), который должен быть сохранен для последующего использования вашим слотом лямбда-функции.Я бы предположил, что то же самое относится и к vecIndex, так как он выглядит как переменная цикла, которую вы описали в своем вопросе, поэтому он меняет свое значение и может быть уничтожен после завершения цикла, но это зависит от фактического контекста вашего приложения.Напротив, переменная vec, вероятно, нуждается в захвате по ссылке, поскольку вы хотите изменить «глобальный» вектор, а не его локальную копию, созданную для лямбда-функции.

Предполагая, что мы приходим к следующему объявлениюлямбда-функции:

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

, которая выражает тот факт, что vec должно быть захвачено по ссылке, в то время как переменные vecIndex и newEdit должны быть получены по их значениям.

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...