【问题标题】:Qt Architecture Advice Needed需要 Qt 架构建议
【发布时间】:2013-09-16 23:21:48
【问题描述】:

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

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

  • 主窗口 继承自 QWidget,它拥有许多 GUI 小部件(菜单栏、工具栏、视口、树视图...等)
  • 系统 从 GUI 执行所有其他操作(数学、几何、IO、数据处理等,并保存具有可绘制组件的“场景”对象。)它还具有单例模式来为自己创建一个全局实例。

我使用 Qt 信号槽机制在 MainWindow 和 System 之间进行通信,实际上 MainWindow 有信号,而 System 有槽。我的问题从这里开始,如何从 System 向 MainWindow 插槽发出信号?当我在 System object 中定义 MainWindow 时,它给了我很多错误。 MainWindow 中的正常系统引用不会出错。但是当我在 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;

当然 Actions 有槽 action() 那么如何从 System 访问 MainWindow?

【问题讨论】:

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


    【解决方案1】:

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

    为了将信号从 System 传递到 MainWindow,您需要使 MyActionList of Sytem 发出任何接收器(在您的情况下为 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 组件发出的信号。

    【讨论】:

    • 它看起来真的很简单,我无法想象。为什么将 MainWindow 中的系统操作作为信号引用。谢谢
    【解决方案2】:

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

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

    【讨论】:

      猜你喜欢
      • 2014-11-01
      • 1970-01-01
      • 1970-01-01
      • 2013-01-02
      • 1970-01-01
      • 2011-06-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-21
      相关资源
      最近更新 更多