【发布时间】:2016-10-21 12:28:04
【问题描述】:
在这一点上,我在何时发出信号与直接调用另一个类中的方法(同一线程)之间处于两难境地。例如,在我正在做的教程中,我将 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);
}
}
【问题讨论】:
-
你能改变你的文本格式,让眼睛更容易阅读吗?另外,一段代码可能会更清楚地说明问题。
-
您是否将视图设置为
ViewManger?你不应该在那里建立这些联系吗?很难说我们什么时候对这些课程一无所知。 -
按要求完成。请参考代码。谢谢!
-
好吧,在这种情况下,它几乎没有任何区别。您可以从外部连接到这些信号,但如果您不希望发生这种情况,也许最好直接调用
m_setupTab的方法。 -
所以你的意思是,使用 m_setupTab.functionName(param) 直接在 SetupViewManager::onConnected() 中调用 Setuptab 中的方法是正确的,而不是发出信号然后连接信号/插槽。对吗?
标签: c++ qt signals-slots