2012-03-11 5 views
0

Я рассматриваю переход между экранами меню в игре с помощью QStateMachine. Тем не менее, я не уверен, как запустить код (например, show() a QWidget) при переходе между состояниями. Я могу сделать это довольно легко с помощью простых старых сигналов (см. Код с комментариями), но я полагаю, что, возможно, я мог бы сделать какую-нибудь причудливую анимацию при переключении экранов с использованием переходов.Переход между экранами меню с помощью QStateMachine

Вот мой код:

Edit: обновлены согласно предложению Koying в.

ApplicationWindow.h:

#include <QtGui> 
#include <QStateMachine> 

#include "MainMenu.h" 
#include "LoadGameMenu.h" 

class ApplicationWindow : public QMainWindow 
{ 
    Q_OBJECT 
public: 
    ApplicationWindow(); 
private slots: 
    void mainMenuButtonClicked(); 
    void loadGameMenuButtonClicked(); 
private: 
    MainMenu* mainMenu; 
    LoadGameMenu* loadGameMenu; 

    QStateMachine stateMachine; 

    QStackedWidget* stack; 
}; 

ApplicationWindow.cpp:

ApplicationWindow::ApplicationWindow() 
{ 
    resize(800, 600); 

    stack = new QStackedWidget(this); 

    mainMenu = new MainMenu(); 
    setCentralWidget(mainMenu); 
    loadGameMenu = new LoadGameMenu(); 

    QState* mainMenuState = new QState(); 
    QState* loadGameMenuState = new QState(); 

    QAbstractTransition* loadTransition = mainMenuState->addTransition(
     mainMenu, SIGNAL(loadGameClicked()), loadGameMenuState); 
    connect(loadTransition, SIGNAL(triggered()), this, SLOT(loadGameMenuButtonClicked())); 

    QAbstractTransition* mainMenuTransition = loadGameMenuState->addTransition(
     loadGameMenu, SIGNAL(backToMainMenuClicked()), mainMenuState); 
    connect(mainMenuTransition, SIGNAL(triggered()), this, SLOT(mainMenuButtonClicked())); 

    stateMachine.addState(mainMenuState); 
    stateMachine.addState(loadGameMenuState); 

    stateMachine.setInitialState(mainMenuState); 
    stateMachine.start(); 
} 

void ApplicationWindow::mainMenuButtonClicked() 
{ 
    setCentralWidget(mainMenu); 
} 

void ApplicationWindow::loadGameMenuButtonClicked() 
{ 
    setCentralWidget(loadGameMenu); 
} 

LoadGameMenu.h:

#include <QtGui> 

class LoadGameMenu : public QWidget 
{ 
    Q_OBJECT 
public: 
    LoadGameMenu(); 
signals: 
    void backToMainMenuClicked(); 
private: 
    QPushButton* loadGameButton; 
    QPushButton* backToMainMenuButton; 
}; 

LoadGameMenu.cpp:

#include "LoadGameMenu.h" 

LoadGameMenu::LoadGameMenu() 
{ 
    loadGameButton = new QPushButton(tr("Load")); 
    backToMainMenuButton = new QPushButton(tr("Main Menu")); 

    QObject::connect(backToMainMenuButton, SIGNAL(clicked()), 
     this, SIGNAL(backToMainMenuClicked())); 

    QVBoxLayout* layout = new QVBoxLayout(); 
    layout->addWidget(loadGameButton); 
    layout->addWidget(backToMainMenuButton); 
    layout->setContentsMargins(300, 400, 300, 200); 
    setLayout(layout); 
} 

MainMenu.h:

#include <QtGui> 

class MainMenu : public QWidget 
{ 
    Q_OBJECT 
public: 
    MainMenu(); 
signals: 
    void newGameClicked(); 
    void loadGameClicked(); 
private slots: 
    void exit(); 
private: 
    QPushButton* newGameButton; 
    QPushButton* loadGameButton; 
    QPushButton* exitGameButton; 

    QMenu* fileMenu; 
}; 

MainMenu.cpp:

#include "MainMenu.h" 

MainMenu::MainMenu() 
{ 
    newGameButton = new QPushButton(tr("New Game"), this); 
    loadGameButton = new QPushButton(tr("Load Game")); 
    exitGameButton = new QPushButton(tr("Exit")); 

    QObject::connect(newGameButton, SIGNAL(clicked()), this, SIGNAL(newGameClicked())); 
    QObject::connect(loadGameButton, SIGNAL(clicked()), this, SIGNAL(loadGameClicked())); 
    QObject::connect(exitGameButton, SIGNAL(clicked()), qApp, SLOT(quit())); 

    QVBoxLayout* layout = new QVBoxLayout(); 
    layout->addWidget(newGameButton); 
    layout->addWidget(loadGameButton); 
    layout->addWidget(exitGameButton); 
    layout->setContentsMargins(300, 200, 300, 200); 
    setLayout(layout); 
} 

void MainMenu::exit() 
{ 
    if(QMessageBox::question(
     this, 
     tr("Exit?"), 
     tr("Do you really want to exit the game?"), 
     QMessageBox::Yes | QMessageBox::No, 
     QMessageBox::No 
     ) == QMessageBox::Yes 
    ) 
    { 
     qApp->quit(); 
    } 
} 

main.cpp:

#include <QtGui> 

#include "ApplicationWindow.h" 

int main(int argv, char **args) 
{ 
    QApplication app(argv, args); 

    ApplicationWindow window; 
    window.show(); 

    return app.exec(); 
} 

Итак, как я могу вызвать какое-либо поведение или действие при переходе?

Cheers.

ответ

2

Чтобы на самом деле что-то сделать при переходе состояния, вам необходимо подключиться к сигналу triggered() перехода, например.

QAbstractTransition* trMainLoad = mainMenuState->addTransition(mainMenu, SIGNAL(loadGameClicked()), loadGameMenuState); 
connect(trMainLoad , SIGNAL(triggered()), SLOT(...)); 
+0

Cheers. Я сделал это, но теперь я получаю: «Необработанное исключение в 0x779815de (ntdll.dll) в Hello Notepad.exe: 0xC0000005: Доступ к чтению с ошибкой 0xabababaf.' Исключение происходит внутри' mainMenuButtonClicked() '- am I не предполагается дважды вызывать 'setCentralWidget'? Я обновил свой оригинальный пост своим новым кодом. – Mitch

+0

В соответствии с 'setCentralWidget()' doc: 'QMainWindow берет на себя ответственность за указатель виджета и удаляет его в соответствующее время. ', Поэтому ваш mainMenu, вероятно, будет уничтожен, когда вы выполните' setCentralWidget (loadGameMenu); ' – Koying

+0

Не подходит когда нет ссылок на указатель слева? Как еще я могу показать разные 'Виджеты' (экраны) внутри' QMainWindow'? Я делаю это только из-за неопытности - я открыт для других вариантов. – Mitch

Смежные вопросы