Qt架构建议需要

时间:2013-09-16 23:21:48

标签: c++ qt user-interface singleton signals-slots

我有一个使用QGLWidget进行绘图的Qt应用程序(只是一个用于3D绘图的视口......)

应用程序中有两个主要类。

  • 主窗口 继承自QWidget,它包含许多GUI小部件(菜单栏,工具栏,视口,树视图等)
  • 系统 GUI中的所有其他操作(数学,几何,IO,数据处理等)是否包含具有可绘制组件的“Scene”对象。)此外,它还具有Singleton模式,可以为自己创建一个全局实例。

我使用Qt信号槽机制在MainWindow和System之间进行通信,实际上MainWindow有信号而System有槽。我的问题从这里开始,如何从System发送到MainWindow插槽?当我在System对象中定义MainWindow时,它给了我很多错误。 MainWindow中的Normaly System引用不会出错。但是当我在System.h中包含MainWindow的头文件时,系统引用在MainWindow端“'System'中给出错误:'::'左边的符号必须是一个类型”。

基本上我的结构看起来像这样。

// MainWindow.h
#include "System.h"
class MainWindow : public QWidget
{
    Q_OBJECT
public:
    QToolBar* MyToolBar; // etc...
    MainWindow()
    {
        ConnectSignals();
    }
    void ConnectSignals() { connect(my_action, SIGNAL(triggered()), System::GetInstance()->Actions, SLOT(action())); }
}
// System.h
#include "MainWindow.h" // if I wrote this, it gives me error in compile time.
class System
{
    static bool m_instance;
    static System* m_system;

    // private constructor
    System()
    {
        Actions = new MyActionList();
    }

public:

    MyActionList* Actions;

    System* GetInstance()
    {
        if (!m_instance)
        {
            m_system = new System();
            m_instance = true;
            return m_system;
        }
        else { return m_system; }
    }
}
// System.cpp
bool System::m_instance = false;
System* System::m_system = NULL;

当然,动作有插槽动作() 那么如何从System访问MainWindow?

2 个答案:

答案 0 :(得分:2)

你的方法中的问题是MainWindow和System之间的循环依赖 - MainWindow包括System,System包括MainWindow。

为了将信号从System传递到MainWindow,您需要使Sytem的MyActionList发出任何接收器(在您的情况下为MainWindow)可以处理的信号。您绝对不需要将MainWindow内容包含在系统中 - 保持后端(系统)独立于任何GUI组件。只需将System封装到您的MainWindow类中,并将MyActionList信号连接到MainWindow插槽。你需要在你的MainWindow中有这样的东西:

connect(my_action, SIGNAL(triggered()), System::GetInstance()->Actions, SLOT(action()));
connect(System::GetInstance()->Actions, SIGNAL(systemSignal()), this, SLOT(handleSystemSignal()));

其中systemSignal()是从System或其MyActionList组件发出的信号。

答案 1 :(得分:1)

正如@vahancho所说,你应该在GUI和其他系统之间保持分离。另一种方法是引入一个委托对象来处理两者之间的通信。

此外,如果您在问题中显示内联代码,则会增加循环依赖的可能性。将实现移动到.cpp文件并使用前向声明,而不是在可能的情况下在其他头文件中包含标头。这也有加速编译的好处,你会注意到大型项目。