PDA

View Full Version : Dialog Class inheriting QDialog Disappears Quickly After Loading.



shandib1823
12th May 2011, 01:43
Hi Guys,

So this problem has stumped me for a while. I have a class that inherits QDialog. When I call it from my class that inherits QObject, it disappears quickly after loading.

I have read many posts about making sure you create the dialog on the heap rather than the stack. I am following this advice but am still having troubles.

I have included my relevant code as well as a diagram showing the hierarchy of our program.

http://i1234.photobucket.com/albums/ff419/chevaliarNoir/diagram.png



//GameLogic.h

#include <vector>
#include <string>
#include <iostream>
#include <ctime>
#include <QObject>
#include "PlayerMenu.h"
#include "AI.h"
#include "GameBoard.h"
#include <QtGui/QApplication>
#include <qpointer.h>
using namespace std;

class GameLogic : public QObject
{
Q_OBJECT
QPointer<PlayerMenu> player_menu; //the menu for the player
Player* human_player;

public:
//constructor
GameLogic(string player_name, int num_of_AI, QWidget *parent = 0);

//destructor
~GameLogic();
};//end of Class
#endif




// GameLogic.cpp : Liars Dice
#include "GameLogic.h"
#include "time.h"
#include <iostream>

//Constructor with user defined number of AI players 1-4
GameLogic::GameLogic (string player_name, int num_of_ai, QWidget *parent)
{
player_menu = new PlayerMenu(parent);

//set up the rest of the connectors
connect(player_menu, SIGNAL(sig_makeBet(int, int)), this, SLOT(bet(int, int)));
connect(player_menu, SIGNAL(sig_startRound()), this, SLOT(slot_startRound()));
connect(player_menu, SIGNAL(sig_moveMade()),this, SLOT(moveMade()));

player_menu->show();
}



#ifndef PLAYERMENU_H
#define PLAYERMENU_H

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string>
#include "ui_PlayerMenu.h"
#include <qdialog.h>
#include "GameBoard.h"

//class GameLogic;

using namespace std;
class PlayerMenu : public QDialog
{
Q_OBJECT
public:
PlayerMenu(QWidget *parent=0);
~PlayerMenu();
...
....
}#endif


//PlayerMenu.cpp : Liar's Dice
#include "PauseMenu.h"
#include <qpushbutton.h>
#include <qmessagebox.h>
#include <iostream>
#include <sstream>

//Default constructor
PlayerMenu::PlayerMenu(QWidget *parent)
: QDialog(parent)
{
//set board
ui.setupUi(this);//playermenu

//initialize variable
move_not_made = true;
player_move = 0;
sec = 0;

//set these values to prevent players from
//making illegal moves.
minDie = 0;
minVal = 0;
ui.sb_diceCount->setMinimum(minDie);
ui.tb_newsFeed->setPlainText("");

//set listenens for buttons
connect(ui.btn_Bet, SIGNAL(clicked()), this, SLOT(Bet()));
connect(ui.btn_callBluff, SIGNAL(clicked()), this, SLOT(callBluff()));connect(ui.pushButton, SIGNAL(clicked()), this, SLOT(pushedOne()));
connect(ui.btn_callSpotOn, SIGNAL(clicked()), this, SLOT(callSpotOn()));connect(ui.pushButton_2, SIGNAL(clicked()), this, SLOT(pushedTwo()));
connect(ui.pushButton_3, SIGNAL(clicked()), this, SLOT(pushedThree()));
connect(ui.pushButton_4, SIGNAL(clicked()), this, SLOT(pushedFour()));
connect(ui.pushButton_5, SIGNAL(clicked()), this, SLOT(pushedFive()));
connect(ui.pushButton_6, SIGNAL(clicked()), this, SLOT(pushedSix()));
}

Thanks for your help!

Edit:
I forgot to also include that I want the PlayerMenu (QDialog) to be modeless. I have the PlayerMenu interacting with the GameLogic through signals.

The main problem I have is that I want the game to start when I load the dialog.

However if I put a signal in the constructor of PlayerMenu to start the game, then the game starts before the dialog is loaded.

If I use exec() It blocks the game logic until the dialog is closed which defeats the purpose.

rsilva
12th May 2011, 03:25
Use open with a "new" pointer, and connect the signals of accepted and rejected or something else that you need.
The dialog is closing when the function reachs it's end. So, if you don't want to block the main thread, you have two options:

- Open a new thread and run exec;
- Use Dialog::open with new pointer in the same thread and connect it to slots, check the result and delete it;

You can try this too:


void mySlotThatOpensTheDialog()
{
PlayerMenu menu;
menu.exec();
}

void myFunctionThatWillCallTheDialog()
{
QTimer::singleShot(0, this, SLOT(mySlotThatOpensTheDialog()));
}

Lykurg
12th May 2011, 07:00
With "disappear" you mean it's getting closed or just hides behind other windows? On your code I can't see why it should be closed, the only guess I have is that the parent of GameLogic is being deletes and thus the dialog also.

ChrisW67
12th May 2011, 07:05
When you create the player_menu object (Line 9 listing 2) you give it the parent of the containing GameLogic instance. More typically, it would have the GameLogic instance (i.e. this) as its parent. Was this deliberate?

Is there a particular reason for using a guarded pointer around player_menu?

shandib1823
12th May 2011, 08:10
Thanks for you response! I tried your suggestion and it is still blocking. I am wondering if using a dialog is even the correct way to go. The PlayerMenu (QDialog) is exactly that. It is mean to be the GUI for game play.

The reason why QMainWindow wasn't used was the because of the same problem we are facing now where the Window was disappearing too quickly.

What do you suggest?

Edit:
Yes passing in parent was deliberate. When we would pass in this it was passing in the Game Logic Object. We used a guarded pointer because it was suggested to us by a fellow classmate.

In our main.cpp we create the QMainWindow StartMenu which is still alive so the user just exits the dialog to go back to the main menu so we know that the Qapp.exec() is still alive. The GameLogic is also still alive. I think that the dialog is being destroyed.

Thanks again!

ChrisW67
13th May 2011, 01:43
Is the player_menu object being deleted or just hidden? This example I think captures your structure, and it works:

#include <QtGui>
#include <QDebug>

class PlayerMenu: public QDialog {
Q_OBJECT
public:
PlayerMenu(QWidget *p = 0): QDialog(p) { }
};


class GameLogic : public QObject
{
Q_OBJECT
PlayerMenu *player_menu; //the menu for the player

public:
GameLogic(QString player_name, int num_of_AI, QWidget *parent = 0) {
player_menu = new PlayerMenu(parent);
player_menu->show();
}
~GameLogic() {
delete player_menu;
}
};



class StartMenu: public QMainWindow {
Q_OBJECT
public:
StartMenu(QWidget *p = 0): QMainWindow(p), gl(0) {
setCentralWidget(new QLabel("Main Window", this));

gl = new GameLogic("dummy", 1, this);
}
~StartMenu() {
delete gl;
}
public slots:
private:
GameLogic *gl;
};

int main(int argc, char *argv[])
{
QApplication app(argc, argv);


StartMenu m;
m.show();
return app.exec();
}
#include "main.moc"



The reason I asked about your QPointer is that I think you wanted a QScopedPointer in order that it do the memory deallocation during destruction.