I am using Qt and have made it so that two dialogs
appear before my centralwidget
. Inside my second dialog (playerInfo
) I created a QcomboBox
and a QlineEdit
that takes in an int and a QString
. I then store those values into my player class. However when I create my centralwidget
and try to pass the player objects into it, it segfaults.
my main.cpp
int main( int argv, char* argc[] ) {
int numberPlayers = 0;
QApplication app( argv, argc );
MainWindow mw;
numPlayers pPlayers; //first dialog that prompts the user to enter in how many players
numberPlayers = pPlayers.returnInput();
playerInfo *pInfo = new playerInfo(numberPlayers, &mw); //user enters in each players info based off number of players
pInfo->show();
return app.exec();
}
playerInfo Dialog:
#include "playerinfo.h"
using namespace std;
playerInfo::playerInfo( int players, MainWindow *mw, QWidget *parent) :
QWidget(parent)
{
max_players = players;
wm = mw; //set wm to point to the address of the mainwindow object
setFixedSize(400, 400);
layout= new QVBoxLayout;
this->setLayout(layout);
title = new QLabel(tr("Please enter the following information:"));
layout->addWidget(title);
lineEdit = new QLineEdit; // create line edit
layout->addWidget(lineEdit);
comboBox = new QComboBox; // create combo box and add items to it
QStringList items = QStringList() << "Hat" << "Car" << "Shoe" << "SpaceShip" << "Basketball" << "Ring";
comboBox->addItems(items);
layout->addWidget(comboBox);
okay = new QPushButton(tr("Accept"));
layout -> addWidget(okay);
connect(okay, SIGNAL(clicked()), this, SLOT(storeInfo()));
}
QString playerInfo::getName() const
{
return lineEdit->text();
}
int playerInfo::getIndex() const
{
return comboBox->currentIndex();
}
void playerInfo::storeInfo()
{
hide();
index = getIndex();
name = getName();
wm->setPlayerData(index, name, pCounter);
pCounter++;
if (pCounter != max_players)
{
show();
}
else if (pCounter == max_players)
{
wm->setGUIWidgets(max_players);
wm->createCentralWidget();
wm->show();
}
}
My centralwidget.cpp:
#include "centralwidget.h"
#include <iostream>
#include <ctime>
#include <cstdlib>
using namespace std;
CentralWidget::CentralWidget(Player *players[0], int input): QWidget() {
for (int i = 0; i < input; i ++)
{
p.append(players[i]); << still segfaulting
// p[i] = players[i]; // segfaulting here <<<
}
}
I figured out the area that is causing my program to segfault is when i try and pass the addresses of the players I passed in from playerInfo Dialog
into private variables of the CentralWidget
class. (p[i] = players[i];
). Am I passing by reference incorrectly?
If there is anymore information you need (like the header files) please let me know. Thanks for any help.
Edit ::
#ifndef CENTRALWIDGET_H
#define CENTRALWIDGET_H
#include <QWidget>
#include <QtGui>
#include "player.h"
class CentralWidget: public QWidget {
Q_OBJECT
private:
QVector<Player> *p;
private slots:
public:
CentralWidget(Player *players[0], int input);
};
#endif
mainwindow.h:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QtGui>
#include <iostream>
#include "guiplayervertical.h"
#include "centralwidget.h"
class MainWindow : public QMainWindow {
Q_OBJECT
private:
Player *players[4];
GUIPlayer* guiPlayers[4];
QWidget *centralWidget;
int input;
QList<int> index;
QList<QString> name;
public:
MainWindow();
void setPlayerData(int _index, const QString &_name, int i);
void setGUIWidgets(int input);
void createCentralWidget();
};
#endif
mainwindow.cpp
#include "mainwindow.h"
using namespace std;
MainWindow::MainWindow() {
}
void MainWindow::setPlayerData(int _index, const QString &_name, int i)
{
index.append(_index); // index is a member variable declared somewhere in your mainwindow.h
name.append(_name); // name is a member variable declared somewhere in your mainwindow.h
players[i] = new Player(name[i], index[i]);
guiPlayers[i] = new GUIPlayerVertical( players[i]);
}
void MainWindow::setGUIWidgets(int input)
{
if (input == 2)
{
addDockWidget( Qt::LeftDockWidgetArea, guiPlayers[0] );
addDockWidget( Qt::RightDockWidgetArea, guiPlayers[1] );
}
else if (input == 3)
{
addDockWidget( Qt::LeftDockWidgetArea, guiPlayers[0] );
addDockWidget( Qt::LeftDockWidgetArea, guiPlayers[1] );
addDockWidget( Qt::RightDockWidgetArea, guiPlayers[2] );
}
else
{
addDockWidget( Qt::LeftDockWidgetArea, guiPlayers[0] );
addDockWidget( Qt::LeftDockWidgetArea, guiPlayers[1] );
addDockWidget( Qt::RightDockWidgetArea, guiPlayers[2] );
addDockWidget( Qt::RightDockWidgetArea, guiPlayers[3] );
}
}
void MainWindow::createCentralWidget()
{
centralWidget = new CentralWidget(&players[0], input);
setCentralWidget( centralWidget );
}
I have not really dug up the issue you encountered, because your code is too connected, and still misses some information. For example, the user's input is not defined, so if the number of players exceeded 4, it would have segfaulted.
However, some of the coding practices in place are worth some refactoring. Since you are having issues with the assignment of p
, which is copied from a pointer to an array passed as parameter, I suggested you switch to a more flexible and less error-prone method. Using std::vector
or, in this case, QVector
, you benefit from a variable-size array, with better memory management, instead of recreating yourself another container, or relying on a fixed-size array.
Start at the member of your class, and declare
private:
QVector<Player*> players;
Then, fill your container using
players.append( new Player(name[i], index[i]) );
When passing the vector as parameter to the constructor of your other class, use a const reference of the same type, this is the equivalent of passing a single pointer, not the whole object
CentralWidget(const QVector<Player*>& players);
Note that using the container, you do not need to also give the array size separately. Finally, this simplifies a lot of the remaining changes. You can now pass the whole member as parameter
centralWidget = new CentralWidget(players);
And simply copy it using
p = players;
No need for the for
loop anymore.