Home > Mobile >  QT Layout not adding properly
QT Layout not adding properly

Time:05-06

I'm currently learning Qt by making a sort of "RecipeBook" application. It has a function that currently should only add layouts from QMap to my main QLayout. Unfortunately, said error occurs:

error that occured

It happens most of the times when adding the last layout, but it's not a rule. I experimented much with this code, so I'm sorry it's so messy. When I started RefillRecipeLayout function the statement was "while(i != endIterator), but it behaved the same. Below I'm sending you my code:

mainwindow.cpp

void MainWindow::on_recalculateButton_clicked()
{
    currentRecipe.RefreshIngredientsInMap(deleteButtonToIngredientLayoutMap);
    RefillRecipeLayout();
}

void MainWindow::DeleteLayout(QLayout* layout)
{
    ClearLayout(layout);
    delete layout;
}

void MainWindow::ClearLayout(QLayout* layout)
{
    while (layout->count() != 0)
    {
        QLayoutItem* item = layout->takeAt(0);
        delete item->widget();
        delete item;
    }
}

void MainWindow::RefreshRecipeLayout()
{
   ClearLayout(recipeLayout);
}

void MainWindow::RefillRecipeLayout()
{
    ClearLayout(recipeLayout);
    int recipeCount= recipeLayout->count();
    int iCount=0;

    QMap<QPushButton*, QHBoxLayout*>::const_iterator i = deleteButtonToIngredientLayoutMap.constBegin();
    QMap<QPushButton*, QHBoxLayout*>::const_iterator endIterator = deleteButtonToIngredientLayoutMap.constEnd();
    int end = std::distance(i, endIterator);
        while (iCount < end)
        {
          QLayout* layout = i.value();
          int recipeCount = recipeLayout->count();
          auto isEmpty=recipeLayout->isEmpty();
          auto isEnabled = recipeLayout->isEnabled();
          bool exists = recipeLayout;
          recipeLayout->addLayout(layout);
          i  ;
          iCount  ;
        }
}

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QComboBox>
#include <QSpinBox>
#include <QTextEdit>
#include <QLabel>
#include <QPushButton>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QScrollArea>
#include <QScrollBar>
#include "recipe.h"
#include "ingredient.h"
#include <vector>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private slots:
    void on_addIngredient_clicked();

    void on_ExitButton_clicked();

    void on_recalculateButton_clicked();

private:
    Ui::MainWindow *ui;
    QMap<QPushButton*, QHBoxLayout*> deleteButtonToIngredientLayoutMap;
    QComboBox* ingredientUnitComboBox=nullptr;
    QSpinBox* ingredientAmountSpinBox=nullptr;
    QTextEdit* ingredientNameText=nullptr;
    QLabel* recipeAmountLabel=nullptr;
    QLabel* recipeNameLabel=nullptr;
    QComboBox* recipeUnitCBox=nullptr;
    QComboBox* newRecipeUnitCBox=nullptr;
    QScrollArea* scrollArea=nullptr;
    QVBoxLayout* recipeLayout=nullptr;
    QSpinBox* recalculateSpinBox=nullptr;
    QComboBox* recalculateUnitCBox=nullptr;

    void PrepareComboBox(QComboBox* comboBox);
    void DeleteIngredient();
    void DeleteLayout(QLayout* layout);
    void ClearLayout(QLayout* layout);
    void RefillRecipeLayout();
    Unit GetUnitFromCBox(QComboBox* comboBox);
    void RefreshRecipeLayout();

};
#endif // MAINWINDOW_H

RefreshIngredientsFunction from Recipe.cpp (works well as far as I know, I've checked with breakpoints)

void Recipe::RefreshIngredientsInMap(QMap<QPushButton*, QHBoxLayout*> OtherMap)
{


    QMap<QPushButton*, QHBoxLayout*>::const_iterator i = OtherMap.constBegin();
    QMap<QPushButton*, QHBoxLayout*>::const_iterator iteratorEnd = OtherMap.constEnd();
    int count=0;
    while (i != iteratorEnd)
    {
      QHBoxLayout* ingredientLayout=new QHBoxLayout();
      QHBoxLayout* layout = i.value();
      int end = std::distance(OtherMap.constBegin(), OtherMap.constEnd());
      int currentItemIndex=0;
      while(layout->count()>0)
      {
          QWidget* widget = layout->takeAt(0)->widget();

          if (QSpinBox* spinBox = qobject_cast<QSpinBox*>(widget))
              spinBox->setValue(13);

          ingredientLayout->addWidget(widget);



          currentItemIndex  ;
      }
      delete layout;
      OtherMap.insert(i.key(), ingredientLayout);
      i  ;
      count  ;

    }
}

CodePudding user response:

Apart from some code style issues (irrelevant debug lines, don't name iterator "i") in your

void Recipe::RefreshIngredientsInMap(QMap<QPushButton*, QHBoxLayout*> OtherMap)

you are taking the map by copy. Then you are trying to modify it's content by deleting some layouts and inserting other layouts.

delete layout;
OtherMap.insert(i.key(), ingredientLayout);

The delete operation destroys the object your map was pointing to, and then after RefreshIngredientsInMap returns, the original map is pointing to destroyed objects, because the insertions were made on a copy.

  • Related