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

信号与槽的总结

信号与槽的总结

QT中的信号与Linux的信号对比

1)信号源

2)信号的类型

3)信号的处理方式

QT信号与Linux信号的深度对比分析

一、信号源对比

QT信号

  • 用户定义信号

    :由开发者通过

    signals:
    

    关键字在QObject派生类中显式声明

    class MyObject : public QObject {Q_OBJECT
    signals:void mySignal(int param);
    };
    
  • 框架内置信号:QT框架提供的信号(如QPushButton的clicked())

  • 信号触发方式

    :通过

    emit
    

    关键字显式触发

    emit mySignal(42);
    

Linux系统信号

  • 系统预定义信号:由操作系统内核预先定义(如SIGINT、SIGSEGV等)

  • 硬件产生信号:如SIGSEGV(内存访问错误)、SIGFPE(算术异常)

  • 进程间信号

    :通过kill()系统调用发送

    kill(pid, SIGTERM);
    

二、信号类型对比

QT信号类型特征

特性说明
类型安全编译时检查参数类型匹配
带参数可携带任意数量、类型的参数
面向对象必须属于某个QObject派生类
同步/异步默认队列连接(异步),可设置为直接连接(同步)

Linux信号类型特征

特性说明
固定编号标准信号编号1-31,实时信号34-64
无参数仅信号编号,不能携带额外数据
进程级别与特定线程/进程关联,非面向对象
同步触发信号处理函数在信号产生时立即执行

常见Linux信号示例:

SIGINT (2):终端中断信号(Ctrl+C)

SIGKILL (9):强制终止信号

SIGSEGV (11):无效内存访问

SIGTERM (15):终止请求信号

三、处理方式对比

QT信号处理(信号-槽机制)

// 连接方式
QObject::connect(sender, &Sender::valueChanged, receiver, &Receiver::updateValue);// 槽函数声明
public slots:void updateValue(int newValue);**处理特点**:
  1. 多线程安全:自动跨线程事件队列传递
  2. 连接类型:
    • 直接连接(同步执行)
    • 队列连接(异步,接收者线程事件循环处理)
    • 自动连接(默认,根据线程关系自动选择)
  3. 内存管理:自动处理对象生命周期(可使用Qt::UniqueConnection)

Linux信号处理

// 信号处理函数注册
struct sigaction sa;
sa.sa_handler = handler;
sigaction(SIGINT, &sa, NULL);void handler(int sig) {// 信号处理逻辑
}

处理特点

  1. 同步执行:中断当前执行流立即处理
  2. 限制严格:
    • 信号处理函数中只能调用异步信号安全函数
    • 不能使用malloc等非可重入函数
  3. 特殊处理:
    • SIGKILL和SIGSTOP不能被捕获或忽略
    • 某些信号会导致核心转储(如SIGSEGV)

四、关键差异总结

对比维度QT信号Linux信号
抽象级别高层次面向对象机制低层次操作系统机制
参数传递支持复杂参数传递仅信号编号,无参数
线程处理自动处理跨线程通信需要显式处理线程掩码
可靠性可靠,不会丢失非实时信号可能丢失
处理时机通过事件循环异步处理立即中断当前执行流
调试支持可通过QtCreator调试需要gdb等系统级调试工具

五、实际应用场景

QT信号典型用例

  1. GUI事件处理(按钮点击、窗口关闭)
  2. 跨线程通信(工作线程到主线程通知)
  3. 模块间解耦(观察者模式实现)

Linux信号典型用例

  1. 进程控制(优雅终止服务进程)
  2. 异常处理(内存错误、算术异常捕获)
  3. 进程间简单通知(无需复杂数据传递)

六、高级主题

QT信号的高级特性

  1. Lambda表达式连接:

    connect(button, &QPushButton::clicked, [=](){qDebug() << "Button clicked";
    });
    
  2. 信号转发:

    connect(obj1, &ClassA::signalA, obj2, &ClassB::signalB);
    
  3. 信号连接管理disconnect()断开连接

Linux信号的进阶处理

  1. 信号屏蔽:

    sigset_t set;
    sigemptyset(&set);
    sigaddset(&set, SIGINT);
    pthread_sigmask(SIG_BLOCK, &set, NULL);
    
  2. 实时信号处理:

    union sigval value;
    value.sival_int = 42;
    sigqueue(pid, SIGRTMIN, value); // 可携带少量数据
    
  3. 替代方案:更复杂的进程通信建议使用socket、管道等机制

信号槽中connect函数的使用

connect (const QObject *sender, const char * signal ,const QObject * receiver , const char * method , Qt::ConnectionType type = Qt::AutoConnection )

参数说明:

• sender:信号的发送者;

• signal:发送的信号(信号函数);

• receiver:信号的接收者;

• method:接收信号的槽函数;

• type: ⽤于指定关联⽅式,默认的关联⽅式为 Qt::AutoConnection,通常不需要⼿动设定。

在控件的问题上我们需要查阅的问题

内置了哪些信号,信号是何时触发的

内置了哪些槽,槽的作用是什么

一、常见控件的内置信号

  1. 按钮类控件(QPushButton等)

主要内置信号

  • clicked():按钮被鼠标点击或键盘激活时触发
  • pressed():按钮被按下时立即触发
  • released():按钮被释放时触发
  • toggled(bool checked):可切换按钮状态改变时触发
// 示例:连接按钮点击信号
connect(ui->pushButton, &QPushButton::clicked, this, &MainWindow::onButtonClicked);
  1. 文本输入类控件(QLineEdit, QTextEdit)

主要内置信号

  • textChanged(const QString &text):文本内容改变时触发
  • textEdited(const QString &text):用户编辑文本时触发
  • returnPressed():按下回车键时触发
  • editingFinished():编辑完成(失去焦点)时触发
// 示例:实时响应文本变化
connect(ui->lineEdit, &QLineEdit::textChanged,[this](const QString &text){qDebug() << "Current text:" << text;});
  1. 选择类控件(QComboBox, QCheckBox, QRadioButton)

主要内置信号

  • currentIndexChanged(int index):当前选项改变时触发
  • currentTextChanged(const QString &text):当前文本改变时触发
  • stateChanged(int state):复选框/单选按钮状态改变时触发
// 示例:响应下拉框选择变化
connect(ui->comboBox, QOverload<int>::of(&QComboBox::currentIndexChanged),[](int index){qDebug() << "Selected index:" << index;});

二、信号触发时机详解

  1. 用户交互触发
  • 鼠标事件:点击、双击、悬停等
  • 键盘事件:按键按下、释放、输入等
  • 触摸事件:触摸屏交互
  1. 状态变化触发
  • 值改变:如滑块位置、进度条值等
  • 焦点变化:控件获得/失去焦点
  • 可见性变化:显示/隐藏状态改变
  1. 系统事件触发
  • 定时器超时:QTimer的timeout()信号
  • 网络响应:QNetworkReply的finished()信号
  • 文件系统变化:QFileSystemWatcher的fileChanged()信号

三、常见控件的内置槽函数

  1. 基础功能槽
槽函数作用适用控件
setText(const QString &)设置控件文本QLabel, QLineEdit等
clear()清空内容QLineEdit, QTextEdit等
setEnabled(bool)启用/禁用控件所有QWidget派生类
show()/hide()显示/隐藏控件所有QWidget派生类
// 示例:使用内置槽
connect(ui->actionClear, &QAction::triggered,ui->textEdit, &QTextEdit::clear);
  1. 状态控制槽
槽函数作用适用控件
setChecked(bool)设置选中状态QCheckBox, QRadioButton
setCurrentIndex(int)设置当前选项QComboBox, QTabWidget
setValue(int)设置数值QProgressBar, QSlider
// 示例:控制进度条
connect(ui->startButton, &QPushButton::clicked,[this](){ui->progressBar->setValue(0);});

四、槽函数的作用与分类

  1. 数据操作槽
  • 数据获取:如text()value()
  • 数据设置:如setText()setValue()
  • 数据清除:如clear()reset()
  1. 状态控制槽
  • 启用/禁用控制setEnabled()setDisabled()
  • 可见性控制show()hide()setVisible()
  • 状态切换setChecked()toggle()
  1. 视图操作槽
  • 滚动控制scrollToTop()scrollToBottom()
  • 缩放控制zoomIn()zoomOut()
  • 选择控制selectAll()deselect()

五、信号与槽的高级应用

  1. 自动连接命名槽

QT支持特定命名格式的槽函数自动连接:

// 声明
private slots:void on_pushButton_clicked();// 实现
void MainWindow::on_pushButton_clicked() {// 无需显式connect,自动关联名为"pushButton"的按钮点击信号
}
  1. 信号与槽的连接类型
// 五种连接类型
Qt::AutoConnection      // 自动选择(默认)
Qt::DirectConnection    // 同步直接调用
Qt::QueuedConnection    // 异步队列调用
Qt::BlockingQueuedConnection // 阻塞式队列调用
Qt::UniqueConnection    // 唯一连接(防止重复连接)
  1. Lambda表达式作为槽
connect(ui->pushButton, &QPushButton::clicked, [this](){// 可以直接访问类成员ui->label->setText("Button clicked at " + QTime::currentTime().toString());
});

六、最佳实践建议

  1. 信号-槽连接规范
    • 优先使用新式语法(&Sender::signal形式)
    • 避免在构造函数中连接尚未完全初始化的对象
  2. 资源管理
    • 使用QPointer管理可能被删除的对象
    • 及时断开不再需要的连接(disconnect)
  3. 线程安全
    • 跨线程连接使用QueuedConnection
    • 避免在不同线程间直接操作GUI控件
  4. 性能优化
    • 高频信号考虑节流(throttling)或防抖(debouncing)
    • 大量连接时考虑使用QSignalMapper或lambda统一处理

自定义槽函数

本质:自定义的一个普通的成员函数

可以让QTCreator自动生成

自定义信号

本质:成员函数

函数的定义是QT自己生成的,作为程序员只需要写函数声明即可

signals:自定义信号的关键字

emit:完成信号的发射(emit可以省略)

信号和槽也可以带参数

发射信号的时候,把参数传给对应的参数

信号的参数和槽的参数一致

1)类型匹配

2)个数,信号的参数要多于槽的参数

信号槽存在的意义:解耦合

代码要达到的要求:高内聚,低耦合

具体含义为:对程序影响很小,写代码的时候,某个代码的功能被集中在一起

disconnect的使用方式:类似于connect

lambda表达式简化槽函数的定义

http://www.dtcms.com/a/267472.html

相关文章:

  • spring加载外部properties文件属性时,读取到userName变量值和properties文件的值不一致
  • 每日学习问题记录
  • 四、jenkins自动构建和设置邮箱
  • Matplotlib 安装部署与版本兼容问题解决方案(pyCharm)
  • nginx部署发布Vite项目
  • H3C WA6322 AP版本升级
  • 2 大模型高效参数微调;prompt tunning
  • (LeetCode 每日一题) 1394. 找出数组中的幸运数 (哈希表)
  • Vue前端项目接收webSocket信息
  • uniapp 国密sm2加密
  • 国产数据库之达梦DM:破甲成蝶
  • php协程
  • 【内存】Linux 内核优化实战 - net.ipv4.tcp_tw_reuse
  • Spring boot之身份验证和访问控制
  • FreeCAD傻瓜教程-拉簧拉力弹簧的画法及草图的附着位置设定和Part工作台中形体构建器的妙用
  • C#扩展方法全解析:给现有类型插上翅膀的魔法
  • spring中 方法上@Transation实现原理
  • Flink-Source算子状态恢复分析
  • 机器视觉对位中的常见模型与技术原理
  • HTML网页应用打包Android App 完整实践指南
  • 【Project】基于kafka的高可用分布式日志监控与告警系统
  • openstack安装并初始化
  • 智能自主运动体的革命:当AI学会奔跑与协作 ——从单机定位到群体智能的跨越
  • 2025年的前后端一体化CMS框架优选方案
  • 未来趋势:AI与量子计算对服务器安全的影响
  • 博弈论基础-笔记
  • RTX5可以在中断中调用的API
  • 08_容器化与微服务:构建弹性架构
  • Ubuntu 22.04 修改默认 Python 版本为 Python3 笔记
  • Hbase2.6.2集群部署(最新版)