有没有办法在不存储连接对象的情况下断开对lambda函数的Qt
连接?
我知道如果我存储从connect函数返回的QMetaObject::Connection
可能会这样做,但我并不是真的想这样做,因为会有很多这样做。我主要连接到lambda函数,以避免创建一堆一次性方法和对象,似乎我需要做所有那些SLOTs
更优选的簿记。
答案 0 :(得分:15)
假设连接:
QObject::connect(senderInstance, &Sender::mySignal, this, []() {
// implement slot as a lambda
});
然后您可以通过以下方式轻松断开连接:
QObject::disconnect(senderInstance, &Sender::mySignal, this, nullptr);
这会断开this's
的所有Sender::mySignal
个广告位;但是,只有一个这样的插槽是很常见的,因此最终的结果是断开连接简单且没有副作用。
答案 1 :(得分:7)
您可以使用虚拟对象:
QObject *obj = new QObject(this);
QObject::connect(m_sock, &QLocalSocket::readyRead, obj, [this](){
obj->deleteLater();
当obj被销毁时,连接断开,因为你在连接上传递了obj。
答案 2 :(得分:4)
以下两种隐藏簿记问题的方法。
首先,我们维护一个std::vector
,在销毁时,我们将其从源头断开:
typedef std::shared_ptr<void> listen_token;
struct disconnecter {
QMetaObject::Connection conn;
disconnecter( QMetaObject::Connection&& c ):conn(std::move(c)) {}
~disconnecter() { QObject::disconnect(conn); }
};
template<class F, class T, class M>
listen_token QtConnect( T* source, M* method, F&& f ) {
return std::make_shared<disconnecter>(
QObject::connect( source, method, std::forward<F>(f));
);
}
typedef std::vector<listen_token> connections;
然后我们连接如下:
connections conns;
conns.emplace_back( QtConnect( bob, &Bob::mySignal, [](QString str){ std::cout << "Hello World!\n"; } ) );
当矢量被销毁时,连接对象也会被破坏。
这类似于处理其他信号/槽系统的方式,其中侦听器跟踪令牌,然后返回它。但是在这里,我将断开对象保持在一个不透明的类型中,以清除破坏时的连接。
请注意,复制该向量将延长连接的生命周期。如果消息发送到类的特定实例,则在类中存储connections
实例,并且在实例销毁后不会收到消息。
根据@lpapp发现的第二种方法,如果你有一个lambda,你只想响应一个信号只调用一次,然后断开连接:
template<class F>
struct auto_disconnect_t {
F f;
std::shared_ptr<QMetaObject::Connection> conn;
template<class U>
auto_disconnect_t(U&& u):
f(std::forward<U>(u)),
conn(std::make_shared<QMetaObject::Connection>())
{}
template<class... Args>
void operator()(Args&&... args)const{
QObject::disconnect(*conn);
f( std::forward<Args>(args)... );
}
};
template<class T, class M, class F>
void one_shot_connect( T* t, M* m, F&& f ) {
typedef typename std::decay<F>::type X;
auto_disconnect_t<X> helper(std::forward<F>(f));
*helper.conn = QObject::connect( t, m, helper );
};
这里我们one_shot_connect( bob, &Bob::mySignal, [](QString str) { std::cout << "Hello\n" } );
,下次信号触发时我们收到消息,然后断开连接。
我在处理你的lambda之前断开连接,以防lambda导致信号触发或者什么。
答案 3 :(得分:1)
这是写这篇文章的唯一方法:
QMetaObject::Connection connection =
QObject::connect(psender, &MyClass::mySignal, [] () { /* Do the work */ });
QObject::disconnect(connection);
有关断开连接方法的参考,请参阅documentation。
bool QObject :: disconnect(const QMetaObject :: Connection&amp; connection)[静态]
断开连接。
如果连接无效或已断开连接,请不执行任何操作并返回false。
在一天结束的时候,你仍然会用插槽来保存书籍,只有当你真的需要本地化时,lambda似乎更加本地化,所以这取决于你的个人喜好,我认为。 / p>