C++ 使用C++;11 lambda函数将单击事件连接到函数
在GUI应用程序中,我使用了很多按钮。这些按钮标记为C++ 使用C++;11 lambda函数将单击事件连接到函数,c++,qt,c++11,lambda,C++,Qt,C++11,Lambda,在GUI应用程序中,我使用了很多按钮。这些按钮标记为pbxx,其中xx是网格布局中按钮的行号和列号。按下按钮时,需要突出显示该按钮。今天我读了关于lambda函数的内容&我想我会尝试在代码中实现它 在我的GUI显示类(继承QMainWindow的类)中,我有一个名为: make_connections(); 这将使我的所有按钮连接(所有信号都连接到按钮点击()上的单个插槽)。我在这里添加了代码: GuiDisplay类 GuiDisplay类的make_connections函数 构建给了我
pbxx
,其中xx
是网格布局中按钮的行号和列号。按下按钮时,需要突出显示该按钮。今天我读了关于lambda函数的内容&我想我会尝试在代码中实现它
在我的GUI显示类(继承QMainWindow的类)中,我有一个名为:
make_connections();
这将使我的所有按钮连接(所有信号都连接到按钮点击()上的单个插槽)
。我在这里添加了代码:
GuiDisplay类
GuiDisplay类的make_connections函数
构建给了我以下错误
'pb_label' is not captured
所以我想,好吧,那么做以下事情似乎没有错:
connect(pb_ptr, &QPushButton::clicked, [this, &pb_label]{on_pushbutton_clicked(pb_label);});
构建时的错误消失了,但是每当执行此代码时,我的GUI应用程序意外崩溃。不确定原因。这里有任何帮助吗?谢谢Piotr Skotnicki和Simple,您的建议都很有效。我可能应该读得更深入一些,我会在捕获列表中看到[=] 因此,导致问题的一行代码可以是:
connect(pb_ptr, &QPushButton::clicked, [this, pb_label]{on_pushbutton_clicked(pb_label);});
或
谢谢Piotr Skotnicki和Simple,你的两个建议都很有效。我可能应该读得更深入一点,我会在捕获列表中看到[=] 因此,导致问题的一行代码可以是:
connect(pb_ptr, &QPushButton::clicked, [this, pb_label]{on_pushbutton_clicked(pb_label);});
或
您的错误是由于使用了对临时标签的引用。
pb_标签
仅在GuiDisplay::make_connections
期间存在。您的lambda由Qt存储,并且将在每次触发信号时被引用。发生这种情况时,您将引用已销毁的对象
因此,建立连接的正确方法是:
connect(pb_ptr, &QPushButton::clicked, [=]{ on_pushbutton_clicked(pb_label); });
从Qt 5.2开始,添加了过载,该过载将在对象生命周期结束时自动断开。在这种情况下,连接将是:
connect(pb_str, &QPushButton::clicked, this, [=]{ on_pushbutton_clicked(pb_label); });
也就是说,当您可以简单地执行以下操作时,不应在此处使用lambda:
connect(pb_ptr, &QPushButton::clicked, this, &GuiDisplay::on_pushbutton_clicked);
然后修改您的GuiDisplay::on_button_clicked
以不接受任何参数。您可以通过调用:来获取GuiDisplay::on_button_clicked
中的对象名称,这将:
返回指向发送信号的对象的指针
然后只需使用获取pb\u标签
:
此属性包含此对象的名称
因此,您只需将pb\u标签
替换为:sender()->objectName()
直接插槽连接优于lambda的原因有几个:
pb\u标签存储临时lambda和临时QString
QObject
的函子
您的错误是由于使用了对临时标签的引用。
pb_标签
仅在GuiDisplay::make_connections
期间存在。您的lambda由Qt存储,并且将在每次触发信号时被引用。发生这种情况时,您将引用已销毁的对象
因此,建立连接的正确方法是:
connect(pb_ptr, &QPushButton::clicked, [=]{ on_pushbutton_clicked(pb_label); });
从Qt 5.2开始,添加了过载,该过载将在对象生命周期结束时自动断开。在这种情况下,连接将是:
connect(pb_str, &QPushButton::clicked, this, [=]{ on_pushbutton_clicked(pb_label); });
也就是说,当您可以简单地执行以下操作时,不应在此处使用lambda:
connect(pb_ptr, &QPushButton::clicked, this, &GuiDisplay::on_pushbutton_clicked);
然后修改您的GuiDisplay::on_button_clicked
以不接受任何参数。您可以通过调用:来获取GuiDisplay::on_button_clicked
中的对象名称,这将:
返回指向发送信号的对象的指针
然后只需使用获取pb\u标签
:
此属性包含此对象的名称
因此,您只需将pb\u标签
替换为:sender()->objectName()
直接插槽连接优于lambda的原因有几个:
pb\u标签存储临时lambda和临时QString
QObject
的函子
按值捕获
pb_标签
,即[这个,pb_标签]
或者您可以使用[=]
按值捕获pb_标签
,即[这个,pb_标签]
或者您可以使用[=]
FWIW,当通过引用捕获时,[这个,&pb_标签]
,然后是原始对象(捕获的引用指向的对象)在退出建立连接时被销毁,这就是为什么您会遇到崩溃fwiw,当通过引用捕获时,[此,&pb_标签]
,然后是原始对象(捕获的引用指向该对象)从make_connections
退出时被破坏,这就是为什么你会遇到crashesI我认为值得一提的是,假设使用Qt 5.2或更新版本,如果你需要在某个对象被破坏时自动断开连接,你可以将该对象作为@thuga Fair point传递,实际上我甚至从我引用的Qt wiki中删除了它。我从来没有r费心从Qt 5.1升级,我在一种没有人使用Qt 5.2的非理性思维下工作。我已经更新了答案。我认为值得一提的是,假设使用Qt 5.2或更新版本,如果在某个对象被销毁时需要自动断开连接,可以将该对象作为