Tom Mclaughlin
Tom Mclaughlin

Reputation: 31

Dynamically adding widgets to gridLayout Qt

I am having a bit of difficulty with some code. I am super rather new to Qt so it is entirely possible that I am simply ignorant to the problem I am having.

Basically, I am blocking out a program so that I can add the specifics of it later. I want to be able to create a grid of buttons, and when one of those buttons is pressed, another shape to replace it.

I am able to make my button grid, have it be scrollable, and have the button call it its position on the grid when pressed. However, when I try and use those coordinates to add another button to the grid, Qt crashes.

Here's my code so far:

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <cmath>
#include <QLabel>
#include <QMainWindow>
#include <QVBoxLayout>
#include <QGridLayout>
#include <QApplication>
#include <QPushButton>
#include <QScrollArea>
#include <QDebug>
#include <QString>
#include <QSignalMapper>
#include <QStringList>
#include <QLayoutItem>



MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
 {
    ui->setupUi(this);
    populateViewGrid(); //I wanted to see if I could add in a scrollbar 
                        //from outside the main window. Could this be causing 
                        // the issue?
 }

void MainWindow::populateViewGrid()
{
QScrollArea*scrollArea = new QScrollArea(this);
QWidget*central = new QWidget(this);
QGridLayout*gridLayout = new QGridLayout(central);
QSignalMapper *signalMapper = new QSignalMapper(central);
for (int i = 0; i < 3; i++)
{
    for (int j = 0; j < 3; j++) 
    {
        QString position= QString("%1,%2").arg(i).arg(j);
        QPushButton* button = new QPushButton("addTrack",central);
        gridLayout->addWidget(button, i, j);
        connect(button, SIGNAL(clicked()),signalMapper, SLOT(map()));
        signalMapper->setMapping(button, position);
    }
}

connect(signalMapper, SIGNAL(mapped(QString)),this, SLOT(addTrack(QString )));

central->setLayout(gridLayout);   

scrollArea->setWidget(central);
setCentralWidget(scrollArea);
}



void MainWindow::addTrack(QString position)
{

QStringList query = position.split(",");
int x;
x=query.at(0).toInt();
        int y;
        y=query.at(1).toInt()    ;

QPushButton *Ifthisworks=new QPushButton(this);

//This first line is where is crashes. I know this due to having the code
//laced with qDebugs. From all of my google searches and such, it seems that 
// something simple should be wrong and I can't find it. 

QLayoutItem * existingitem = gridLayout->itemAtPosition(x, y);


if(existingitem) {
    gridLayout->removeItem(existingitem);
    delete existingitem;
}
// before I included the above to remove the button from the grid point, the 
//program would crash here. 

gridLayout->addWidget(Ifthisworks, x, y);

}



MainWindow::~MainWindow()
{
    delete ui;
}

main.cpp

#include "mainwindow.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();

    return a.exec();
}

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <cmath>
#include <QLabel>
#include <QMainWindow>
#include <QVBoxLayout>
#include <QGridLayout>
#include <QApplication>
#include <QPushButton>
#include <QMainWindow>
#include <QScrollArea>
#include <QSignalMapper>
#include <QHash>
//unrelated question, do I need the above in my code? I know not all of them 
//used, but do I need includes in this file as well?

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
    void populateViewGrid();
QGridLayout *gridLayout;

public slots:

void addTrack(QString);
private:
    QScrollArea*scrollArea;
    QWidget * central;
    QPushButton *Ifthisworks;
    QSignalMapper *signalMapper;
    QPushButton *clockViews;

    Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H

If you could help me understand how to not make Qt crash there and also add a button, that would be fantastic =)

So some background real quick incase you are looking at my code and are scratching your head. I'm a mechanical engineer who should have probably been an electrical or computer engineer and knows enough about coding to get myself into these kinds of messes. For the most part, I searched for what I wanted Qt to do and hacked it all together to hopefully make it work. Any bit of deeper understanding you can share would be more than welcome.

Thank you for your time.

Upvotes: 3

Views: 4145

Answers (2)

thuga
thuga

Reputation: 12931

You are initializing a local variable called gridLayout in your MainWindow::populateViewGrid() method:

QGridLayout*gridLayout = new QGridLayout(central);

Then in your MainWindow::addTrack(QString position) method, you are trying to access the member variable called gridLayout which is never initialized.

To fix this, simply initialize the member variable instead of creating a local variable in your MainWindow::populateViewGrid() method:

gridLayout = new QGridLayout(central);

You are doing the same mistake with your other member variables as well. Fix them the same way.

Upvotes: 2

Sebastian Lange
Sebastian Lange

Reputation: 4029

I would go for a different implementation.

Move gridlayout, signalmapper,... to be class members. I personally like also to keep a list of my widgets QList<QPushButton*> for manually deleting or keeping a button cache.

Make the signalmapper to map to index in list or QWidget*. For the example i`ll go with the QWidget* pointer.

QPushButton *newButton = new QPushButton("The new Thing");
QPushButton *oldButton = static_cast<QPushButton*>(widgetPointer);
gridLayout->replaceWidget(oldButton ,newButton);
buttonList->takeAt(buttonList->indexOf(oldButton))->deleteLater()); //if you keep a list..
buttonList->insert(buttonList->indexOf(oldButton),newButton);

Upvotes: 0

Related Questions