直接调用函数与发出信号(Qt-信号和插槽)

诺基亚所有者

在这一点上,我在何时发出信号与直接在另一个类(同一线程)中调用方法的困境。例如,在本教程中,我将Instrument类(模型)的NotifyConnected信号连接到“ this”(也称为“视图管理器”)的onConnected插槽,请参考SetupViewManager :: WireButtons(),代码中的第三行。(我正在使用MVVM设计模式)。这里的信号和插槽是有意义的,因为Instruments类(模型)对视图管理器一无所知。(即,将视图管理器的引用传递给模型是不可以的,因为这会破坏MVVM设计模式。)出色。

我遇到的问题是,在本教程中,接下来,ViewManager的onConnected插槽会发出其他信号,然后我必须继续手动连接到另一个View类的插槽,即SetupTab(请参阅void SetupViewManager :: onConnected和void SetupViewManager ::代码中的WireDisplayUpdate())。

我的问题是,为什么不直接调用SetupTab的方法来替换onConnected插槽中的所有发射?觉得我的代码过于复杂。

加倍努力来发射信号并仅需简单地从我有参考的另一类中调用公共函数(信号)就必须进行一切连接,这有什么好处?它不是多线程应用程序(我知道信号和插槽是线程安全的)。

请赐教。

谢谢。

setupviewmanager.cpp:

#include "setupviewmanager.h"
#include "View/setuptab.h"
#include "Model/instrument.h"
#include "Model/settings.h"
#include "utils.h"

namespace Ps
{
    SetupViewManager::SetupViewManager(QObject *parent,
                                       SetupTab &tab,
                                       Instrument &inst,
                                       Settings &config) :
        QObject(parent),
        m_setupTab(tab),
        m_instrument(inst)
    {
        WireSettings(config);
        config.ParseJsonData();
        WireHostAndPort();
        WireMessages();
        WireButtons();
        WireDisplayUpdate();

        m_setupTab.SetHostName(config.getHostName());
        m_setupTab.SetPort(config.getPortNumber());
        m_setupTab.SetCommands(config.getCommandsAsModel());
        auto long_wait = config.getLongWaitMs();
        auto short_wait = config.getShortWaitMs();
        m_instrument.SetlongWaitMs(long_wait);
        m_instrument.SetShortWaitMs(short_wait);
        emit NotifyStatusUpdated(tr("Long wait Ms: %1").arg(long_wait));
        emit NotifyStatusUpdated(tr("Short Wait Ms: %1").arg(short_wait));
        onDisconnected();
    }

    SetupViewManager::~SetupViewManager()
    {
        Utils::DestructorMsg(this);
    }

    void SetupViewManager::WireSettings(Settings &config)
    {
        connect(&config, &Settings::NotifyStatusMessage, &m_setupTab, &SetupTab::onStatusUpdated);
    }

    void SetupViewManager::WireHostAndPort()
    {
        connect(&m_setupTab, &SetupTab::NotifyHostNameChanged, &m_instrument, &Instrument::onHostNameChanged);
        connect(&m_setupTab, &SetupTab::NotifyPortChanged, &m_instrument, &Instrument::onPortChanged);
    }

    void SetupViewManager::WireMessages()
    {
        connect(&m_instrument, &Instrument::NotifyErrorDetected, &m_setupTab, &SetupTab::onStatusUpdated);
        connect(&m_instrument, &Instrument::NotifyStatusUpdated, &m_setupTab, &SetupTab::onStatusUpdated);
        connect(this, &SetupViewManager::NotifyStatusUpdated, &m_setupTab, &SetupTab::onStatusUpdated);
    }

    void SetupViewManager::WireButtons()
    {
        connect(&m_setupTab, &SetupTab::NotifyConnectClicked,&m_instrument, &Instrument::Connect);
        connect(&m_instrument, &Instrument::NotifyConnected, &m_setupTab, &SetupTab::onConnected);
        connect(&m_instrument, &Instrument::NotifyConnected, this, &SetupViewManager::onConnected);

        connect(&m_setupTab, &SetupTab::NotifyDisconnectClicked,&m_instrument, &Instrument::Disconnect);
        connect(&m_instrument, &Instrument::NotifyDisconnected, &m_setupTab,&SetupTab::onDisconnected);
        connect(&m_instrument, &Instrument::NotifyDisconnected, this, &SetupViewManager::onDisconnected);

        connect(&m_setupTab, &SetupTab::NotifySendClicked,&m_instrument, &Instrument::onSendRequest);
        connect(&m_instrument, &Instrument::NotifyDataSent,&m_setupTab, &SetupTab::onDataSent);

        connect(&m_setupTab, &SetupTab::NotifyReceiveClicked,&m_instrument, &Instrument::onReceiveRequest);
        connect(&m_instrument, &Instrument::NotifyDataReceived,&m_setupTab, &SetupTab::onDataReceived);
    }

    void SetupViewManager::WireDisplayUpdate()
    {
       connect (this, &SetupViewManager::NotifyConnectEnabled, &m_setupTab, &SetupTab::onConnectEnabled);
       connect (this, &SetupViewManager::NotifyDisconnectEnabled, &m_setupTab, &SetupTab::onDisconnectEnabled);
       connect (this, &SetupViewManager::NotifyDirectCommandsEnabled, &m_setupTab, &SetupTab::onDirectCommandsEnabled);
       connect (this, &SetupViewManager::NotifyControlTabEnabled, &m_setupTab, &SetupTab::onControlTabEnabled);
    }

    void SetupViewManager::onConnected()
    {
        emit NotifyConnectEnabled(false); // HERE. Why not just call method directly with m_setupTab.onConnectEnabled(false); etc...?
        emit NotifyDisconnectEnabled(true);
        emit NotifyDirectCommandsEnabled(true);
        emit NotifyControlTabEnabled(true);
    }

    void SetupViewManager::onDisconnected()
    {
        emit NotifyConnectEnabled(true);
        emit NotifyDisconnectEnabled(false);
        emit NotifyDirectCommandsEnabled(false);
        emit NotifyControlTabEnabled(false);
    }
}
库巴并没有忘记莫妮卡

信号和插槽用于解耦类,因此它们无需明确知道谁使用其功能以及如何使用它们。在许多情况下,解耦是软件设计的理想特性。当然,这本身并不是目的,当它可以帮助您推理代码的正确性并使其更易于维护时,它很有用。解耦有助于理解/合理化代码,因为它可以导致较小的代码单元,您可以单独对其进行分析。另一种看待问题的方法是关注点分离:让一个代码单元做一件事情,例如将一个类集中在功能的一个方面。

当您有一对类并希望决定是否将它们配对时,请考虑是否可以将它们与其他类一起使用。A可以耦合B,但是可以使用耦合该对的接口C代替B吗?如果是这样,则必须使用一些去耦模式,而信号时隙模式就是其中之一。

例如,让我们比较这两个接口如何影响与用户代码的耦合。目的很简单:将调试输出添加到对象的析构函数中:

class QObject {
  ...
  Q_SIGNAL void destroyed(QObject * obj = Q_NULLPTR);
};

class QObjectB {
  ...
  virtual void on_destroyed();
};

int main() {
  QObject a;
  struct ObjectB : QObjectB {
    void on_destroyed() override { qDebug() << "~QObjectB"; }
  } b;
  QObject::connect(&a, &QObject::on_destroyed, []{ qDebug() << "~QObject"; });
}

信号插槽接口使您可以轻松地向现有对象添加功能,而无需对其进行子类化。这是Observer模式的特别灵活的实现这样可以使您的代码与对象的代码脱钩。

第二种实现使用模板方法相似的模式,强制进行更紧密的耦合:要对进行ObjectB销毁,必须具有一个派生类的实例,在其中可以实现所需的功能。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

使用Qt信号和插槽与直接调用方法

来自分类Dev

信号和插槽的工作

来自分类Dev

信号和插槽 qt 关闭插槽

来自分类Dev

Qt信号和插槽:权限

来自分类Dev

Qt插槽和信号语法

来自分类Dev

Qt信号和插槽故障

来自分类Dev

插槽和信号无限循环

来自分类Dev

带信号和插槽的QScopedPointer

来自分类Dev

QT5中的信号和插槽

来自分类Dev

Qt:连接文本中的信号和插槽

来自分类Dev

Qt信号和插槽传递数据

来自分类Dev

在QT中清除信号和插槽的命名

来自分类Dev

Qt-2类信号和插槽

来自分类Dev

Qt 5.3信号和插槽,简单函数和Lambda表达

来自分类Dev

Qt插槽和信号。获取插槽接收器对象

来自分类Dev

Qt插槽和信号未连接:无此信号

来自分类Dev

Qt 插槽和信号:MainWindow 中没有匹配函数

来自分类Dev

Qt信号插槽:发送信号但未调用插槽

来自分类Dev

可以多次链接信号和插槽吗?

来自分类Dev

PyQt4信号和插槽-QToolButton

来自分类Dev

类之间的Python信号和插槽

来自分类Dev

ListView信号和菜单元素的插槽

来自分类Dev

Qt信号/插槽问题

来自分类Dev

信号和插槽编辑按钮被禁用(Qt Designer 4.8)

来自分类Dev

如何在Qt中创建动态信号和插槽?

来自分类Dev

第二类内的QT信号和插槽

来自分类Dev

如何更改QT中信号和插槽的时序?

来自分类Dev

Qt信号和插槽-没有匹配的通话功能

来自分类Dev

Qt信号和插槽:如何获取已更改的数据?