我正在QT编写一个程序,它目前有一个GameEngine
(数据处理)类和一个MainWindow
(GUI)类。
GameEngine
and和MainWindow
类的单个实例归int main
函数所有。
MainWindow
实例有一个User Action
按钮,它将打开一个名为Dialog_UserAction
的QDialog类的实例。 QDialog的实例由MainWindow
拥有,MainWindow
也是QDialog的父级(在Dialog_UserAction
实例打开时禁用GameEngine
GUI)。
我的问题是需要在QDialog和Dialog_UserAction
实例之间连接许多事件(信号)。
有什么简单的方法可以达到这个目的吗?
我已经尝试过将GameEngine
的信号通过MainBoard
转发到Dialog_UserAction
,反之亦然。这有效,但对于这项任务来说这是一个非常混乱的解决方案。
我也试过让Main
归User Action Button clicked
所有,但我不知道如何在主要背景下对Dialog_UserAction
事件做出反应。
最后,我还尝试让GameEngine
归MainBoard
实例拥有,这将是简单的解决方案(除了Dialog_UserAction
GUI不会被禁用,而GameEngine
被打开)。但是,我真的更喜欢所有与GUI相关的实例都不在class GameEngine : public QObject
{
Q_OBJECT
signals:
void someSignalToDialog(void);
public slots:
void on_someSignalFromDialog();
}
上下文中。
Gaminagineha:
class Dialog_UserAction: public QObject
{
Q_OBJECT
signals:
void someSignalToGameEngine(void);
public slots:
void on_someSignalFromGameEngine();
}
Dialog_UserAction.h:
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
QApplication::setWindowIcon(QIcon(":/images/MageKnightLogo.jpg"));
GameEngine gameEngine;
Window_MainBoard mainBoard;
mainBoard.showFullScreen();
return a.exec();
}
Main.cpp的:
#include "Dialog_UserAction.h"
...
void Window_MainBoard::on_pushButton_enterUserAction_clicked() {
Dialog_UserAction actionDialog(this);
// connect signals and slots here?
if (actionDialog.exec() == QDialog::Accepted)
{
// Send signal with data to GameEngine
}
}
...
MainBoard.cpp:
Dialog_UserAction
所以,我真正要问的是:有没有简单的方法可以在这个设置中设置信号槽连接,我可以将GameEngine
与MainBoard
连接,而无需转发GameEngine
上下文中的信号?
如果没有,你对我如何以更好的方式处理这个问题有什么建议吗?提前致谢。
由于Dialog_UserAction
对象是单例(只存在一个实例),因此可以让GameEngine
对象将其信号直接连接到Dialog_UserAction
对象。你可以在GameEngine
构造函数中做到这一点。
要轻松访问GameEngine*
对象,只需向其中添加一个返回静态class GameEngine
{
public:
GameEngine()
{
Q_ASSERT(instance_ == nullptr); // Only one instance allowed.
instance_ = this;
}
static GameEngine* instance() noexcept
{ return instance_; }
private:
static GameEngine* instance_;
};
成员的静态成员函数。
Gaminagineha
GameEngine* GameEngine::instance_ = nullptr;
GameEngine.cpp
Dialog_UserAction
您现在可以将GameEngine::instance()
信号连接到GameEngine::Instance()
。
所以,为了澄清,我最终使用了Nikos C建议的Singleton设计模式。
但是我的课程实现方式略有不同,因此希望将其作为一个独立的答案分享。
我发现我需要以某种方式触发对象的构造函数,并认为这可以使用所谓的(我相信)Lazy Initialization方法来完成。此外,类的构造函数应该是私有的,这样只有实例本身才能调用它,从而确保构造函数只被调用一次。
此外,我将const static GameEngine*
method作为class GameEngine
{
public:
const static GameEngine* instance() { // Singleton instance reference getter
if (instance_ == nullptr)
instance_ = new GameEngine(); // This triggers the constructor of the object
return instance_;
}
private:
GameEngine(); // The constructor is made private!
};
类型,以便让对象的访问权限是只读的。
Gaminagineha
// Place this declaration in the top of the file to create the global class instance pointer
// The initial value of the pointer must be nullptr to let the constructor be correctly triggered at the first instance()-call
GameEngine* GameEngine::instance_ = nullptr;
GameEngine.cpp
Main
然后在Dialog_UserAction
和#include "GameEngine.h"
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
Window_MainBoard mainBoard;
const GameEngine* gameEngine = GameEngine::instance(); // Const pointer to the Singleton instance of the GameEngine class (global object)
QObject::connect(gameEngine, SIGNAL(someSignalToDialog), &mainBoard, SLOT(on_someSignalFromGameEngine));
}
(客户端)中,通过在每个上下文中创建一个const类实例指针来使用对Singleton GameEngine实例的访问。
Main.cpp的
#include "GameEngine.h"
// Constructor
Dialog_UserAction::Dialog_UserAction(QWidget *parent) : QDialog(parent), ui(new Ui::Dialog_UserAction) {
ui->setupUi(this);
// Const pointer to the Singleton instance of the GameEngine class (global object)
const GameEngine* gameEngine = GameEngine::instance();
connect(this, SIGNAL(someSignalToGameEngine), gameEngine, SLOT(on_someSignalFromDialog) );
}
Dialog_UserAction.cpp
qazxswpoi