You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Qt MVC架构下,如何实现控制器间的解耦调用?

在Qt的MVC架构下,要实现两个独立控制器的解耦交互,核心思路是避免控制器间直接引用或信号连接,而是通过中间层(模型、事件总线或Qt原生事件)传递状态或事件。以下是几种可行的方案:

方案1:基于模型层的状态同步(最贴合MVC设计)

MVC的核心是模型作为状态中枢,所有控制器围绕模型交互,完全符合解耦要求:

  • 定义共享模型,包含控制矩形显示状态的属性及对应信号
  • 窗口控制器修改模型状态,场景控制器监听模型状态变化并更新视图
// 共享模型类
class AppModel : public QObject
{
    Q_OBJECT
    Q_PROPERTY(bool isRectangleVisible READ isRectangleVisible WRITE setIsRectangleVisible NOTIFY rectangleVisibilityChanged)
public:
    bool isRectangleVisible() const { return m_visible; }
    void setIsRectangleVisible(bool visible) {
        if (m_visible != visible) {
            m_visible = visible;
            emit rectangleVisibilityChanged(visible);
        }
    }
signals:
    void rectangleVisibilityChanged(bool visible);
private:
    bool m_visible = true;
};

// 窗口控制器(按钮所在)
class WindowController : public QObject
{
    Q_OBJECT
public:
    WindowController(AppModel* model, QPushButton* button) : m_model(model) {
        connect(button, &QPushButton::clicked, this, [this](){
            m_model->setIsRectangleVisible(false); // 点击按钮设置隐藏状态
        });
    }
private:
    AppModel* m_model;
};

// 场景控制器
class SceneController : public QObject
{
    Q_OBJECT
public:
    SceneController(AppModel* model, QGraphicsRectItem* rect) : m_model(model), m_rect(rect) {
        connect(m_model, &AppModel::rectangleVisibilityChanged, this, [this](bool visible){
            m_rect->setVisible(visible); // 根据模型状态更新矩形显示
        });
    }
private:
    AppModel* m_model;
    QGraphicsRectItem* m_rect;
};

这种方式下,两个控制器仅依赖模型,彼此完全解耦,严格遵循MVC职责划分。

方案2:全局事件总线(通用解耦方案)

如果不想修改模型层,可以实现一个全局事件总线作为事件中转中心:

  • 单例EventBus提供发布/订阅接口
  • 窗口控制器发布隐藏事件,场景控制器订阅并响应
// 事件总线单例类
class EventBus : public QObject
{
    Q_OBJECT
public:
    static EventBus* instance() {
        static EventBus bus;
        return &bus;
    }
    // 发布事件
    void publish(const QString& eventName, QVariant data = QVariant()) {
        emit eventPublished(eventName, data);
    }
    // 订阅事件
    QMetaObject::Connection subscribe(const QString& eventName, const std::function<void(QVariant)>& callback) {
        return connect(this, &EventBus::eventPublished, this, [eventName, callback](const QString& name, QVariant data){
            if (name == eventName) {
                callback(data);
            }
        });
    }
signals:
    void eventPublished(const QString& eventName, QVariant data);
private:
    EventBus() = default;
};

// 窗口控制器
class WindowController : public QObject
{
    Q_OBJECT
public:
    WindowController(QPushButton* button) {
        connect(button, &QPushButton::clicked, this, [](){
            EventBus::instance()->publish("HideRectangle");
        });
    }
};

// 场景控制器
class SceneController : public QObject
{
    Q_OBJECT
public:
    SceneController(QGraphicsRectItem* rect) : m_rect(rect) {
        EventBus::instance()->subscribe("HideRectangle", [this](QVariant){
            m_rect->setVisible(false);
        });
    }
private:
    QGraphicsRectItem* m_rect;
};

这种方式下,两个控制器无直接依赖,仅与事件总线交互,解耦程度极高。

方案3:Qt自定义事件(原生API方案)

利用Qt原生事件机制发送自定义事件:

  • 定义自定义事件类
  • 窗口控制器发送事件,场景控制器重写event方法处理
// 自定义事件类
class HideRectangleEvent : public QEvent
{
public:
    static const QEvent::Type EventType;
    HideRectangleEvent() : QEvent(EventType) {}
};
const QEvent::Type HideRectangleEvent::EventType = static_cast<QEvent::Type>(QEvent::User + 100);

// 窗口控制器
class WindowController : public QObject
{
    Q_OBJECT
public:
    WindowController(QPushButton* button, QObject* sceneController) : m_sceneController(sceneController) {
        connect(button, &QPushButton::clicked, this, [this]{
            QCoreApplication::postEvent(m_sceneController, new HideRectangleEvent());
        });
    }
private:
    QObject* m_sceneController;
};

// 场景控制器
class SceneController : public QObject
{
    Q_OBJECT
public:
    SceneController(QGraphicsRectItem* rect) : m_rect(rect) {}
protected:
    bool event(QEvent* event) override {
        if (event->type() == HideRectangleEvent::EventType) {
            m_rect->setVisible(false);
            event->accept();
            return true;
        }
        return QObject::event(event);
    }
private:
    QGraphicsRectItem* m_rect;
};

这种方式利用Qt原生API,无需额外中间类,仅需传递场景控制器指针(可通过依赖注入或全局获取),解耦程度略低于前两种,但依然避免了直接信号连接。

内容的提问来源于stack exchange,提问作者Ascii67

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 04:27:16