Qt开发:实现跨组件的条件触发
场景描述
有一个主界面 ViewpointWidget
,它包含一个3D视图模块 ViewPointModelWidget
。ViewPointModelWidget
内部有一个“清除”按钮 (pushButton_clear
)。
需求:当用户在 ViewpointWidget
中点击“保存”按钮时,如果当前的全局功能模式是“路线标注 (RouteAnnotation
)”,则需要自动触发 ViewPointModelWidget
的“清除”功能。
1:状态传递与存储
首先,确保 ViewpointWidget
能够接收并存储当前的全局功能模式ID。 SceneDetailWidget
已经负责管理页面切换,并通过调用 ViewpointWidget::onButtonGroupClicked(int id)
将模式ID传递了进来。
只需要在 ViewpointWidget
中利用好这个现有的机制。
文件: ViewpointWidget.cpp
// 该函数由上层调用,用于通知当前的功能模式
void ViewpointWidget::onButtonGroupClicked(int id)
{// 将接收到的id保存到成员变量m_curPage中m_curPage = static_cast<SceneDetailpage>(id);// ... 其他根据id更新UI的逻辑 ...
}
ViewpointWidget
可以判断当前功能模式的能力。
2:定义意图清晰的信号
为了实现解耦,ViewpointWidget
不应该直接关心“如何清除”,而应该只表达“需要清除”的意图。通过定义一个信号来完成这一点。
文件: ViewpointWidget.h
class ViewpointWidget : public QWidget
{Q_OBJECT
// ...
signals:// 定义一个无参数的信号,清晰地表达“请求清除标注”的意图void requestClearAnnotations();
// ...
};
接着,在“保存”按钮的槽函数中,根据存储的状态来发射信号。
文件: ViewpointWidget.cpp
void ViewpointWidget::onSaveClicked(/*...*/)
{// ... 原有的保存逻辑 ...// 检查存储的当前页面IDif (m_curPage == RouteAnnotation) {// 如果是路线标注模式,就发射请求信号emit requestClearAnnotations();}
}
至此,ViewpointWidget
在正确的时机,发出了一个清晰请求。
3:连接
将 ViewpointWidget
发出的 requestClearAnnotations
信号,连接到 ViewPointModelWidget
的 onClickedClearButton(bool checked)
槽上。
这里出现了参数不匹配的问题:信号是无参数的,而槽需要一个 bool
参数。
可以在 connect
语句中,使用一个Lambda表达式完成参数的适配。
文件: ViewpointWidget.cpp
(构造函数中)
ViewpointWidget::ViewpointWidget(QWidget *parent) :QWidget(parent),ui(new Ui::ViewpointWidget)
{ui->setupUi(this);// ... 其他connect ...// 将本类的请求信号,连接到一个Lambda表达式connect(this, &ViewpointWidget::requestClearAnnotations, this, [this]() {// 在Lambda内部,我们拥有完整的上下文,可以安全地调用子控件的槽函数// 并手动为槽函数提供一个默认参数ui->widget_view->onClickedClearButton(false);});
}
connect
的接收者是this
(即ViewpointWidget
实例),信号是requestClearAnnotations
。connect
的响应者是一个Lambda函数[this](){...}
。- 当信号被发射时,这个Lambda函数被执行。
- Lambda函数内部捕获了
this
指针,因此它可以访问ui->widget_view
(即ViewPointModelWidget
的实例)。 - 在Lambda函数体内,我们直接调用了
onClickedClearButton
,并为它传递了一个false
作为参数,解决了参数不匹配的问题。