Russian Qt Forum

Qt => Вопросы новичков => Тема начата: SlimSlot от Август 02, 2011, 12:34



Название: QDialog + QLayout Ошибка
Отправлено: SlimSlot от Август 02, 2011, 12:34
Добрый день!

Есть класс, унаследованный от QDialog
В конструкторе создается QGridLayout, который устанавливается this->setLayout(p_GridLayout)
Далее вызывается функция

Код:
    QComboBox* l_pComboBox_Field = new QComboBox();
    QComboBox* l_pComboBox_TypeLimit = new QComboBox();
    QLineEdit* l_pLineEdit_ValueLimit = new QLineEdit();
    QHBoxLayout* l_pHBoxLayout_LimitLine = new QHBoxLayout();

    l_pHBoxLayout_LimitLine->addWidget(l_pComboBox_Field);
    l_pHBoxLayout_LimitLine->addWidget(l_pComboBox_TypeLimit);
    l_pHBoxLayout_LimitLine->addWidget(l_pLineEdit_ValueLimit);

    l_pComboBox_Field->addItem("");
    for (int i = 0; i < p_SqlModel->columnCount(); i++)
        l_pComboBox_Field->addItem(p_SqlModel->headerData(i, Qt::Horizontal).toString());

    connect(l_pComboBox_Field, SIGNAL(currentIndexChanged(QString)), this, SLOT(slot_SelectFilterColumn(QString)));

    p_GridLayout->addLayout(l_pHBoxLayout_LimitLine, iCountLimitLines, 0, 1, 3);

    iCountLimitLines++;

Суть в чем. При определенных действиях добавляется строка в GridLayout в виде HBoxLayout динамически.

Сам диалог создается из другого окна QMainWindow

Код:
Limit* l_pLimit = new Limit(p_User, p_Model);

    l_pLimit->setModal(true);
    l_pLimit->exec();

При запуске вылезает ошибка
Цитировать
---------------------------
Microsoft Visual C++ Runtime Library
---------------------------
Runtime Error!

This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.

Попробовал поотлаживать.
Валится где-то на месте, связанным с layout в какой-то структуре, где сам layout как я понимаю не инициализирован и разыменывание приводит к краху.

Не могу понять в чем ошибка. Помогите пожалуйста, хоть в какую сторону смотреть.


Название: Re: QDialog + QLayout Ошибка
Отправлено: GreatSnake от Август 02, 2011, 13:43
Цитировать
В конструкторе создается QGridLayout, который устанавливается this->setLayout(p_GridLayout)
Ну дык и где ентот конструктор?


Название: Re: QDialog + QLayout Ошибка
Отправлено: SlimSlot от Август 02, 2011, 13:49
Цитировать
В конструкторе создается QGridLayout, который устанавливается this->setLayout(p_GridLayout)
Ну дык и где ентот конструктор?
А, да, забыл конструктор.
Вот же он

Код:
Limit::Limit(LoginUser* user, QSqlQueryModel* model, QWidget *parent): QDialog(parent)

{
    p_user = user;
    p_SqlModel = model;
    p_GridLayout = new QGridLayout();
    this->setLayout(p_GridLayout);
    CreateUI();
}

где user - это объект, класс которого унаследован от QObject
в CreateUI вызывается моя функция AddLimitLine:

Код:
QLabel* l_pLable_Information = new QLabel("тратата");
    QPushButton* l_pBtn_OK = new QPushButton("ОК");
    QPushButton* l_pBtn_Cancle = new QPushButton("Отмена");
    QPushButton* l_pBtn_AddLimitLine = new QPushButton("Добавить строку ограничения");
    QVBoxLayout* l_pVBoxLayout_OkCancle = new QVBoxLayout();



    l_pVBoxLayout_OkCancle->addWidget(l_pBtn_OK);
    l_pVBoxLayout_OkCancle->addWidget(l_pBtn_Cancle);

    p_GridLayout->addLayout(l_pVBoxLayout_OkCancle, 0, 4, 2, 1);
    p_GridLayout->addWidget(l_pBtn_AddLimitLine, 1, 0, 1, 1);
    p_GridLayout->addWidget(l_pLable_Information, 0, 0, 1, 1);
    AddLimitLine();




Название: Re: QDialog + QLayout Ошибка
Отправлено: GreatSnake от Август 02, 2011, 14:05
где инициализация iCountLimitLines?


Название: Re: QDialog + QLayout Ошибка
Отправлено: SlimSlot от Август 02, 2011, 14:32
Вот черт.
Теперь понял почему так произошло.
Спасибо огромное!!!!


Название: Re: QDialog + QLayout Ошибка
Отправлено: SlimSlot от Август 03, 2011, 17:25
В продолжение темы...
Добавление строки фильтра я сделал.
Теперь удаление строки фильтра
Вот  код указанного ранее слота slot_SelectFilterColumn
Код:
void Limit::slot_SelectFilterColumn(QString ColumnName)
{
    if (sender()->objectName().toInt() == iCountLimitLines-1)
        AddLimitLine();

    if (ColumnName == "")
    {
        QComboBox* cmb_ = (QComboBox*) this->findChild<QComboBox*>("ComboType" + QString::number(sender()->objectName().toInt()));
        cmb_->clear();
        //QMessageBox::about(0, sender()->objectName(), sender()->objectName());
        DeleteLimitLine(sender()->objectName().toInt()+1);
        return;
    }



    QComboBox* cmb = (QComboBox*) this->findChild<QComboBox*>("ComboType" + sender()->objectName());

    if (cmb==NULL)
        return;

    cmb->clear();
    cmb->addItem("Равно");
    cmb->addItem("Не равно");
    cmb->addItem("Больше");
    cmb->addItem("Меньше");


    QSqlRecord rec = p_SqlModel->record(1);

    if (rec.field(ColumnName).type() == QVariant::DateTime)
        cmb->addItem("Между");
    else if (rec.field(ColumnName).type() == QVariant::String)
    {
        cmb->addItem("Содержит");
        cmb->addItem("Не содержит");
    }
}

Здесь при выборе пустого элемента для фильтрации должна удаляться следующая строка фильтра - функция DeleteLimitLine, в которую передается номер текущей строки фильтра + 1

Сама функция вот
Код:
void Limit::DeleteLimitLine(int iIndex)
{
    QLayoutItem* f = p_GridLayout->itemAtPosition(iIndex, 0);


    int iCount = f->layout()->count();
    for (int i = 0; i < iCount; i++)
    {

        QWidget* p_wgt = f->layout()->itemAt(0)->widget();
        f->layout()->removeWidget(p_wgt);
        p_wgt->close();
        delete p_wgt;
    }


    p_GridLayout->removeItem(f);
    delete f;

    p_GridLayout->setSizeConstraint(QLayout::SetMinimumSize);
    this->resize(p_GridLayout->sizeHint().width(), p_GridLayout->sizeHint().height());


    iCountLimitLines--;
}
Т.е. получаем QLayoutItem - Layout строки фильтра по индексу.
Смотрим количество виджетов в этом Layout и удаляем каждый
Далее удаляем сам Layout.

Удаление проходит нормально. Только проблема в том что после удаления не перестраивается размер диалога. Точнее он перестраивается, но криво. Такое ощущение что в нем есть еще одна как бы невидимая строка - размер как раз подходит. Но строки нет.
Но.
Если до строки
Код:
p_GridLayout->setSizeConstraint(QLayout::SetMinimumSize);
Выводить сообщение (любое) QMessageBox
То диалог нормально перестраивается.
Причем это поэтапно выглядит так
1. Удаляются виджеты и Layout
2. Размер формы перестраивается как будто с еще одной строкой, которой нет
3. Показывается сообщение
4. Размер формы перестраивается идеально

Подскажите пожалуйста, почему такое может быть?