当前位置: 首页 > article >正文

qt 槽函数中获取发射信号的对象(widget)

概述

在Qt中,槽函数(slot)默认是不直接知道是哪个对象(widget)发送了信号的。这是因为Qt的信号和槽机制设计上是解耦的,即信号的发送者和接收者之间不需要有直接的依赖或了解。然而,如果确实需要在槽函数中获取到发送信号的widget的引用,有几种方法可以实现这一目的:

1. 使用QObject::sender()

在槽函数中,可以使用QObject::sender()函数来获取发送信号的对象的指针。这个函数返回一个指向QObject的指针,需要根据实际情况将它转换为合适的类型。

void MyClass::mySlot() {  
    QWidget *senderWidget = qobject_cast<QWidget*>(sender());  
    if (senderWidget) {  
        // 现在可以使用senderWidget了  
    }  
}

注意: 这种方法在大多数情况下是可行的,但是有几个需要注意的点:

如果信号的发送者不是QWidget或其子类,qobject_cast 将返回 nullptr
如果信号和槽连接是跨线程的(即信号和槽在不同的线程中),则 sender() 可能返回 nullptr(在Qt 5.x中是这样,但在Qt 6中这一行为有所改变)。

2. 在连接时传递信息

如果需要在槽函数中获取到发送者的具体信息,但又不想依赖sender(),可以在信号和槽的连接时,通过 Lambda 表达式或 QSignalMapper 等方式传递额外的信息。

使用Lambda表达式

connect(senderWidget, &QWidget::clicked, this, [this, senderWidget]() {  
    // 在这里可以直接使用senderWidget  
    this->mySlot(senderWidget);  
});  
  
// 注意:上面的示例并不完全遵循Qt的信号和槽机制,因为Lambda表达式直接调用了槽函数。  
// 更常见的是,将Lambda作为槽函数本身,或者在Lambda内部调用一个真正的槽函数,并传递senderWidget作为参数。  
  
void MyClass::realSlot(QWidget *widget) {  
    // 使用widget  
}

使用QSignalMapper

QSignalMapper 是一个在Qt 4中常用的工具类,用于将多个信号映射到同一个槽上,并携带额外的信息。不过,在Qt 5及更高版本中,由于Lambda表达式的普及,QSignalMapper 的使用已经不那么常见了。

QSignalMapper *signalMapper = new QSignalMapper(this);

connect(button1, SIGNAL(clicked()), signalMapper, SLOT(map()));  
signalMapper->setMapping(button1, 1); // 假设 1 是 button1 的标识符  

connect(button2, SIGNAL(clicked()), signalMapper, SLOT(map()));  
signalMapper->setMapping(button2, 2); // 假设 2 是 button2 的标识符  

connect(signalMapper, SIGNAL(mapped(int)), this, SLOT(onButtonClicked(int)));

对于每个想要映射的信号,需要将其连接到 QSignalMappermap() 槽上,并设置一个唯一的标识符(这里以整数为例)。然后,将 QSignalMappermapped() 信号连接到槽函数上。

void MyClass::onButtonClicked(int id) {  
    switch (id) {  
    case 1:  
        // 处理 button1 被点击的情况  
        break;  
    case 2:  
        // 处理 button2 被点击的情况  
        break;  
    default:  
        // 处理未知标识符的情况  
        break;  
    }  
}

注意:虽然这个例子使用了整数作为标识符,但 QSignalMapper 也支持使用指针作为标识符。如果想要将 QWidget 指针用作标识符,可以这样做:

//signalMapper->setMapping(button1, 1); 
signalMapper->setMapping(button1, static_cast<QObject*>(button1));  

// ...  
void MyClass::onButtonClicked(QObject *object) {  
    QWidget *widget = qobject_cast<QWidget*>(object);  
    if (widget) {  
        // 处理对应的 widget  
    }  
}

在大多数情况下,如果只是需要知道是哪个按钮被点击了,直接使用 sender() 方法可能更为直接和简单。QSignalMapper 的主要优势在于它允许将多个信号映射到同一个槽上,并传递额外的信息,这在处理大量相似对象(如多个按钮、复选框等)时非常有用。


http://www.kler.cn/a/299748.html

相关文章:

  • 我是如何写作的?
  • MySQL备忘录
  • Linux文件原生操作
  • JavaScript
  • 【C语言】内存函数
  • 步进电机加减速公式推导
  • 【题解单调队列优化dp】划分
  • 数据结构(14)——哈希表(1)
  • Winform实现石头剪刀布小游戏
  • 基于 SpringBoot 的实习管理系统
  • com.alibaba.druid.pool.DruidDataSource error
  • LVS负载均衡有几种工作方式?
  • 旋翼无人机的应用场景和用途!!!
  • 【安全漏洞】Mybatis-PageHelper 分页SQL注入漏洞
  • 深度学习数据集
  • pandas to_sql函数参数详解
  • 基于深度学习 卷积神经网络resnext50的中医舌苔分类系统
  • 使用@test-library/react的screen中的方法和直接使用getByText,getByTestId等的区别?
  • 面试题—Java基础
  • 计算机网络 ---- 电路交换、报文交换、分组交换性能分析
  • 校园安全无小事,EasyCVR视频综合管理平台助力智慧校园视频监控系统全面升级
  • 二层交换机如何工作
  • 点亮第一盏LED灯,认识stm32最小系统板
  • 【FastAPI】离线使用Swagger UI 或 国内网络如何快速加载Swagger UI
  • 使用libmpeg解码mp3格式文件
  • OPPO 全家桶:Find X8/Pro、Pad3 Pro与Enco X3即将10月登场