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:
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.