Program forgets class and struct memory locations in mousePressEvent, but I can't figure out why



  • I'm having a problem with a board game I've been creating, which has me frustrated.

    It's a board game, where the board is a QGridLayout. Each square of the grid is a class I've called "squareGraphic" (defined in graphics.h), which is a kind of QLabel. squareGraphic contains a various variables, as well as functions and a pointer to a 'position' struct (defined by me in board.h). It also contains a QMouseEvent.

    The board in the game logic is a 3D array of position structs. Each position struct contains two squareGraphic widgets in it - one is the default value of the widget (when no piece is on the square), and the other is the value to be displayed. At the beginning, these point to the same address (I should have made only one squareGraphic widget in each struct and made a variable in squareGraphic that stores the square's default image, which I do intend to; but for now this is what I'm using).

    Note that each squareGraphic contains a pointer to a position struct, which should be the struct that contains that squareGrahpic e.g. if "exampleSquareGraphic" is a squareGraphic in a position struct called "examplePosition", then "exampleSquareGraphic" would contain a pointer to "examplePosition".

    Ultimately I want the user to click on a square (i.e. a squareGraphic), then have the program pass what square was clicked to the game logic, then have the appropriate squareGraphic on the board change what image it shows correspondingly.

    The board initialises just fine, but when I click on a squareGraphic, it seems to forget the value of the struct contained in the squareGraphic. It should be a simple memory problem, but I can't figure out why it's happening. I'll post some code then explain what I've been trying to do.

    Here's how I've defined squareGraphic:

    class squareGraphic : public QLabel
    {
        Q_OBJECT
    public:
    
        explicit squareGraphic(struct position * squarePosition, class gameData * data, QLabel *parent = 0);
        explicit squareGraphic(QLabel *parent = 0);
       ~squareGraphic();
    
    public:
        unsigned int arrayXCoord;
        unsigned int arrayYCoord;
        unsigned int arrayLayNum;
        struct position * thisPosition;
        class gameData * gameData;
        void squareClicked();
        void setCoords(unsigned int layNum, unsigned int XCoord, unsigned int YCoord);
        bool tokenCheck;
    
    protected:
         void mousePressEvent(QMouseEvent *);
    
    signals:
        void clicked();
    
    };
    

    Here's my definition of the 'position' struct:

    struct position
    {
        posType type;
        posColour colour;
        unsigned int mlinStatus;
        squareGraphic * locImg;
        squareGraphic * defaultImg;
        int xCoordWidget;
        int yCoordWidget;
        unsigned int arrayLayNum;
        unsigned int arrayXCoord;
        unsigned int arrayYCoord;
    
        void setCoords(unsigned int layNum, unsigned int XCoord, unsigned int YCoord);
        bool placePiece(enum posColour newToken);
    };
    

    Here's how the squareGraphic widgets and their functions are initialised and defined:

    squareGraphic::squareGraphic(struct position * squarePosition, class gameData * data, QLabel *parent)
        : QLabel(parent)
    {
        tokenCheck = true;
        thisPosition = squarePosition;
        gameData = data;
    
    }
    
    squareGraphic::squareGraphic(QLabel *parent)
        : QLabel(parent)
    {
        tokenCheck = false;
    }
    
    squareGraphic::~squareGraphic()
    {
    
    }
    
    void squareGraphic::setCoords(unsigned int layNum, unsigned int XCoord, unsigned int YCoord)
    {
    
        arrayLayNum = layNum;
        arrayXCoord = XCoord;
        arrayYCoord = YCoord;
    
    }
    
    void squareGraphic::mousePressEvent(QMouseEvent *)
    {
        if(tokenCheck == true)
        {
    
            //std::cout << arrayLayNum << std::endl;
            //std::cout << thisPosition->colour << std::endl;
            // gameData->displayBoard();
            // gameData->placePiece(arrayLayNum, arrayXCoord, arrayYCoord, blackToken);
            emit clicked();
        }
    
    

    Now here's what's confusing me. If I move "std::cout << this->colour << std::endl;" into the function where the board is initialised ("gameData::initBoard()", in board.cpp), it prints the correct values, so I know it's getting initialised. If I move the same expression into "squareGraphic::setCoords()" (ran during the initialisation) in also prints everything correctly. However, the same function in "squareGraphic::mousePressEvent()" prints non-nonsensical memory values. Placing "std::cout << arrayLayNum << std::endl;" in "squareGraphic::mousePressEvent()" prints the correct values.

    So the widget is forgetting the value of the struct but remembering the unsigned ints. I also added "gameData->displayBoard()" (gameData is a class that contains all the data in the program, and displayBoard() prints the board in the command line (used for testing for I started using Qt)) to "squareGraphic::mousePressEvent)", but this also prints nonsensical values. Placing "gameData.displayBoard()" in main.cpp after the initialisation of the board prints the correct values.

    This is really confusing me. It's as if the program is correctly initialising everything, but is only forgetting classes and structs (and nothing else) in squareGraphic::mousePressEvent() (and nowhere else).

    The only function currently being used in game.cpp is the initialisation of the gameData class:

    gameData::gameData()
    {
    
        gameStatus = placing;
        blackPieces.piecesOnBoard = 0;
        blackPieces.piecesUnplaced = numPieces;
        blackPieces.piecesTaken = 0;
        whitePieces.piecesOnBoard = 0;
        whitePieces.piecesUnplaced = numPieces;
        whitePieces.piecesTaken = 0;
    
        tokenImage.blackTokenMap = new QPixmap("resources/blackToken.jpg");
        tokenImage.whiteTokenMap = new QPixmap("resources/whiteToken.jpg");
        tokenImage.emptyTokenMap = new QPixmap("resources/blankSquare.jpg");
        tokenImage.whiteTokenMlinMap = new QPixmap("resources/whiteTokenMlin.jpg");
        tokenImage.blackTokenMlinMap = new QPixmap("resources/blackTokenMlin.jpg");
        tokenImage.horizontalLineMap = new QPixmap("resources/horizontalLine.jpg");
        tokenImage.verticalLineMap = new QPixmap("resources/verticalLine.jpg");
        tokenImage.cornerBottomLeftMap = new QPixmap("resources/cornerBottomLeft.jpg");
        tokenImage.cornerBottomRightMap = new QPixmap("resources/cornerBottomRight.jpg");
        tokenImage.cornerTopLeftMap = new QPixmap("resources/cornerTopLeft.jpg");
        tokenImage.cornerTopRightMap = new QPixmap("resources/cornerTopRight.jpg");
        tokenImage.intersectionBottomMap = new QPixmap("resources/intersectionBottom.jpg");
        tokenImage.intersectionTopMap = new QPixmap("resources/intersectionTop.jpg");
        tokenImage.intersectionBottomMap = new QPixmap("resources/intersectionBottom.jpg");
        tokenImage.intersectionLeftMap = new QPixmap("resources/intersectionLeft.jpg");
        tokenImage.intersectionRightMap = new QPixmap("resources/intersectionRight.jpg");
        tokenImage.intersectionMiddleMap = new QPixmap("resources/intersectionMiddle.jpg");
        initBoard();
        initBoardWidget();
    }
    

    initBoard() and initBoardWidget() are defined in board.cpp. They're too long to copy here, but essentially they just initialise the values in gameData.

    Here's my mainwindow.cpp:

    MainWindow::MainWindow(QWidget *parent)
        : QWidget(parent)
    {
       class gameData gameData;
       QHBoxLayout * appBox = new QHBoxLayout;
       setLayout(appBox);
       appBox->addWidget(gameData.boardWidget);
    
    }
    

    And here's my main.cpp:

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

    There are other functions (mainly in game.cpp) which handle the game logic, but most haven't been applied to the actual program yet, so are irrelevant to this problem.

    The full program can be found here:
    https://github.com/Matulin/MlinConsole

    Sorry for the long post. I hope you can help me with this problem.
    Thanks in advance.



  • Hi Neptefre,
    in mainwindow.cpp you create a local! object on the stack with class gameData gameData;. This object is gone if the constructor of mainwindow end.
    If you create a heap object like this

    MainWindow::MainWindow(QWidget *parent)
        : QWidget(parent)
    {   
       //class gameData gameData;
       gameData *gameData2 = new gameData;
       QHBoxLayout * appBox = new QHBoxLayout;
       setLayout(appBox);
       //appBox->addWidget(gameData.boardWidget);
       appBox->addWidget(gameData2->boardWidget);
    }
    

    the squareGraphic::mousePressEvent in prints out some plausible values



  • @sneubert Thanks for the reply! It seems to have fixed the problem.

    I feel like an idiot now for not realising it was something so simple. It's been driving me mad, and it turns out I wasn't even looking in the right place!

    I'll credit you with a comment in the program.



  • You´r welcome. Don´t be angry with yourself too much. Me and probably every other had for sure some similar issue while writing code. Sometimes if you´r deep inside it´s hard to see the obvious. That´s what this forum is for.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.