2012-03-11 15 views
0

QStateMachineを使用してメニュー画面間の移行を検討しています。しかし、状態間の移行時にいくつかのコード(例:show() a QWidget)を開始する方法が不明です。単純な古いシグナル(コメント付きのコードを参照)で簡単に行うことができますが、トランジションを使用して画面を切り替えるときに、派手なアニメーションを行うことができます。QStateMachineでメニュー画面を切り替える

編集: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(); 
} 

遷移が発生したときの動作や動作をどのようにトリガーしますか?

乾杯。

答えて

2

状態遷移で実際に何かを行うには、トランジションのtriggered()信号に接続する必要があります。

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

乾杯。私はこれをしましたが、今は次のようになっています: 'Hello Notepad.exeの0x779815de(ntdll.dll)で処理されない例外:0xC0000005:アクセス違反が位置0xabababafを読み込んでいます '例外は' mainMenuButtonClicked 'setCentralWidget'を2回呼び出す予定はありませんか?オリジナルの投稿を新しいコードで更新しました。 – Mitch

+0

'setCentralWidget()' doc: 'QMainWindowはウィジェットのポインタの所有権をとり、適切な時刻に削除します.'ので、' setCentralWidget(loadGameMenu);を実行するとmainMenuが破壊される可能性があります。 – Koying

+0

時間は、ポインタへの参照が残っていないことを意味しますか? 'QMainWindow'の中に別の'ウィジェット '(スクリーン)をどのように表示できますか?私は経験不足のためこの方法でしかやってません - 私は他の選択肢にもオープンしています。 – Mitch

関連する問題