【问题标题】:Is sending signals to same object (e.g. this) in Qt an anti-pattern在 Qt 中向同一个对象(例如 this)发送信号是一种反模式
【发布时间】:2017-06-23 04:04:45
【问题描述】:

我想知道在 Qt 中向同一个对象发送信号是否被认为是不好的做法和反模式,或者这是否很好。

我正面临这样的情况:

QObject::connect (this, &MyFoo::ready,
                  this, &MyFoo::execute, 
                  Qt::ConnectionType::QueuedConnection);

然后从内部execute 我想emit ready。这样做的动机是避免深度递归。我的替代方法是从execute 递归调用execute

【问题讨论】:

  • 在我看来,这不是一种反模式,但我看不到任何在设计级别上无法简化的用例。为什么要将呼叫排队执行?一个简单的循环不符合您的需要?如果没有,您可以使用[static] bool QMetaObject::invokeMethod 在没有信号的情况下执行与示例完全相同的操作
  • 只需考虑将信号 (MyFoo::ready) 和插槽 (MyFoo::ready) 放在不同的类中的选项。如果它们可以属于不同的类,您可能会得到更好的设计。如果您的目标只是将插槽调用排队,您可能需要查看此answer

标签: qt


【解决方案1】:

AFAIK,Qt 文档中没有任何内容表明这是一种不好的做法。

我这样做了很多次,特别是在我的对象从线程(侦听 COM 端口或蓝牙连接)收到通知并且需要更新 GUI 的情况下:

MyObject::MyObject()
{
    connect( this, SIGNAL(dataReceived(QString)), this, SLOT(showData(QString)), Qt::ConnectionType::QueuedConnection );
}

void MyObject::receiveSomeData( QString data )
{
    // a worked thread called this function...
    // we are not in the main thread here, it's unsafe to update the GUI,
    // calling showData(data) will lead most likely lead to crashs or Qt warnings
    // so let's delay it's execution by emitting dataReceived!
    emit dataReceived( data );
}

void MyObject::showData( QString data )
{
    // now it's safe to update the GUI...we are back to main thread
    m_ui.label->setText( data );
}

在基于 Qt 的类构造函数中也使用了这种技巧,您需要等待小部件实际可见,然后才能执行一些 GUI 操作(例如,需要访问小部件的大小......在您的构造函数中,布局尚未被视为限制小部件大小的约束)。然后我必须从小部件构造函数中emitsignal,并且此信号连接到将执行初始化的同一小部件​​类的slot,并且Qt::ConnectionType::QueuedConnection 使初始化函数在小部件之后执行实际上是可见的。

可能还有其他相关的情况......

注意:正如 ymoreau 评论 OP,这也可以通过使用 QMetaObject::invokeMethod 来解决,这很可能最终会做同样的事情。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-03-12
    • 1970-01-01
    • 1970-01-01
    • 2021-12-05
    • 1970-01-01
    • 2016-09-01
    • 1970-01-01
    相关资源
    最近更新 更多