Qt应用开发(基础篇)——信号槽 Signals and Slots

这篇具有很好参考价值的文章主要介绍了Qt应用开发(基础篇)——信号槽 Signals and Slots。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、前言

        Qt成为我们今天拥有的灵活而舒适的工具,除了友好和能够快速开发设计师界面,信号槽机制是最大的核心特征,也是区别于其他开发框架最大的优势。

        Qt的信号槽作用于两个对象之间的通信。当一个对象发生了改变,它希望其他关心它的对象能够了解到这些变化。比如一个编辑框A的数据发生了改变,而编辑框B的需要根据A的值发生数据变化,这时候我们使用信号槽机制,A数据变化触发信号,B响应信号做动作。

        我们用来表达算法的语法会显著影响代码的可读性和可维护性,Qt的信号和槽的语法在实践中被证明是非常成功的。语法直观使用简单易于阅读这可以帮助程序员从一开始就正确地进行设计,甚至不必考虑设计模式。这满足安全和高效的图形用户界面编程,Qt希望我们构建更干净、更安全、更符合UNIX精神的系统。

二、Signals and Slots

        要实现对象之间的通讯方法有很多。

        1)初学者可能会通过定时器检测目标对象的属性变化而动作,这类方法缺点很明显,代码乱、耗资源、效率低、无法直接传递多个参数等等。

        2)资深的程序员会使用回调callback机制,这是一种函数指针的用法,想让别人的代码执行自己的代码。把自身需要执行的代码写在一个函数里面,让目标对象去调用此函数,实现对象间的通讯。但是如果多对象类都想要关心目标对象的状态变化,此时需要维护一个列表,以存放多个回调函数的地址(函数指针),对于每一个被关注的对象,都需要做类似的工作,并且对象需要动态销毁的时候,还需要关注这些函数指针的回收,这样的设计效率低且不灵活。

        3)信号槽机制类似于设计模式中的观察者模式(当一个对象状态发生改变的时候,所有依赖于它的对象都得到通知并被自动更新)。被观察者发出信号Signals,观察者监听信号,设计槽函数Slots关联信号实现动作。

Qt应用开发(基础篇)——信号槽 Signals and Slots,QT应用开发,qt,c++,上位机,PC

值得一提的是,信号槽与回调函数的区别,是面试中经常出现的问题。

信号槽优点

        1)松耦合性

        目标对象不需要知道哪个对象关心自己,发出的信号类似于广播,如果有人对信号感兴趣,使用connect连接信号与自身的处理槽函数即可。而回调函数需要目标对象去处理对自己感兴趣的全部对象的函数指针。耦合性明显Qt信号槽机制更优。

        2)类型安全

        需要关联的信号槽的签名需要是相同的,即参数型号、参数个数必须一致。如果不一致的话编译器会报错。

        3)灵活性

        信号槽机制支持一个信号多个槽响应,也可以一个槽响应多个信号,还可以直接信号触发信号(适用于逻辑层信号夹带数据不需要处理直接转发)。

        4)内存安全

        信号槽机制在UI编程上具备优势,能够帮助程序员环节内存泄漏问题,当应用程序创建了一个具有父窗口部件的对象时,该对象被加入父窗口的child列表,当父窗口被销毁时,child列表中的对象被一一删除,子类释放的顺序与构造顺序相反。

信号槽缺点

        1)速度较慢。

        与回调函数相比,信号和槽机制运行速度比直接调用非虚函数慢10倍。照官方说法是需要定位接收信号的对象需要遍历全部关联槽需要编组和接祖传递参数。但依旧能够满足大多数应用的需求,因为1秒钟可以出发200万次这样的信号(i586-500机器,1个信号绑定一个槽函数,绑定两个1秒可以触发120万次)。

信号槽连接类型

        connect连接信号槽第五个参数为连接类型,通常情况下默认为Qt::AutoConnection,自动设置。

类型 描述
Qt::AutoConnection 如果信号与槽在同一个线程中则为Qt::DirectConnection直连、否则为Qt::QueuedConnection队列。
Qt::DirectConnection 直连,发出信号的时候立刻调用槽函数
Qt::QueuedConnection 队列,信号与槽不同线程时,使用此类型
Qt::BlockingQueuedConnection 阻塞队列,等待槽函数返回,信号和槽不可在同一个线程,否则死锁
Qt::UniqueConnection 一个标识,与上述几种组合使用,避免相同信号槽多次连接

信号槽使用注意事项

        1)默认情况下信号槽被多次连接,导致触发信号的时候槽函数就会被多次调用。可以使用Qt::UniqueConnection解决此问题。       

        2)Qt::BlockingQueuedConnection等于一个阻塞的机制,子线程执行信号必须等待主线程返回才会继续往下走,默认不阻塞

        3)多线程中,信号槽连接类型为Qt::QueuedConnection,所以信号触发的时候不会马上执行槽函数,存在实时性的风险

        4)信号触发的速度过快,而槽函数响应不过来。比如当你做一个视频播放器,摄像头的数据一直在刷新,但是界面上刷新不过来,槽函数处理的速度比不上信号触发的速度,如果这时候使用的是Qt::DirectConnection,导致程序可能异常。

        5) 信号槽传递的参数必须是Qt的元对象系统所知道的类型,因为Qt需要复制参数以将它们存储在后台的事件中,否则编译会报错如果需要使用自定义类型作为参数传递,使用Q_DECLARE_METATYPE()注册它。

        6)所有信号的声明都是公有的,所以不能在signals前面加public,private,proteed

        7)信号没有返回值,只需要声明不需要定义。

        7)自定义类必须直接或间接继承自QObject类,并且开头私有声明包含Q_OBJECT,才能使用信号槽机制。

信号槽连接

1)传统写法

        使用SIGNAL()和SLOT()宏中包含参数的规则,传递给SIGNAL()宏的签名必须不少于传递给SLOT()宏的签名。

QLabel *label = new QLabel;
QScrollBar *scrollBar = new QScrollBar;
QObject::connect(scrollBar, SIGNAL(valueChanged(int)),
                  label,  SLOT(setNum(int)));
//带连接类型
QObject::connect(scrollBar, SIGNAL(valueChanged(int)),
                  label,  SLOT(setNum(int)),Qt::AutoConnection);
2)函数指针

        使用函数指针写法连接,优点在于它允许编译器检查信号的参数是否与插槽的参数兼容,参数也可以由编译器隐式转换。

QLabel *label = new QLabel;
QLineEdit *lineEdit = new QLineEdit;
QObject::connect(lineEdit, &QLineEdit::textChanged,
                  label,  &QLabel::setText);
3)直接触发当前函数
void someFunction();
QPushButton *button = new QPushButton;
QObject::connect(button, &QPushButton::clicked, someFunction);
4)Lambda表达式
 QByteArray page = ...;
 QTcpSocket *socket = new QTcpSocket;
 socket->connectToHost("qt-project.org", 80);
 QObject::connect(socket, &QTcpSocket::connected, [=] () {
         socket->write("GET " + page + "\r\n");
     });
5)QOverload

        当存在名称相同,但是参数不同的信号,如果使用函数指针的写法,编译器无法知道我们连接的是哪个信号,编译器会报第二个参数为“unresolved overloaded function type”错误。

Qt应用开发(基础篇)——信号槽 Signals and Slots,QT应用开发,qt,c++,上位机,PC

Qt应用开发(基础篇)——信号槽 Signals and Slots,QT应用开发,qt,c++,上位机,PC

        为了使用函数指针语法连接到这个信号,Qt提供了一个方便的助手QOverload来获取函数指针。

connect(ui->comboBox,QOverload<int>::of(&QComboBox::currentIndexChanged),
       this,&MainWindow::onCboIndexChaned);

识别信号来源

       当有多个对象发送信号都通过一个槽来处理的时候,我们就需要在槽中识别出这些信号然后做相应的处理。

        多个lineEdit编辑框当内容发送变化的时候,我们统一设计一个槽函数来做处理,使用sender()返回发送信号的指针。文章来源地址https://www.toymoban.com/news/detail-635569.html

void QMainWindows::textChaned(QString str)
{
    QLineEdit* edit = dynamic_cast<QLineEdit*>(sender())
    if (edit == ui->Edit_name){
         //do something   
    }
    else if (edit == ui->Edit_number){
        //do something   
    }
}

到了这里,关于Qt应用开发(基础篇)——信号槽 Signals and Slots的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Qt应用开发(基础篇)——颜色选择器 QColorDialog

             QColorDialog 类继承于QDialog,是一个设计用来选择颜色的对话框部件。         对话框窗口 QDialog          QColorDialog 颜色选择器一般用来让用户选择颜色,比如画图工具中选择画笔的颜色、刷子的颜色等。你可以使用静态函数 QColorDialog::getColor() 直接显示对

    2024年02月10日
    浏览(27)
  • Qt应用开发(基础篇)——文本编辑窗口 QTextEdit

             QTextEdit 类继承于QAbstractScrollArea,QAbstractScrollArea继承于QFrame,用来显示富文本和纯文本的窗口部件。 框架类 QFrame https://blog.csdn.net/u014491932/article/details/132188655 滚屏区域基类 QAbstractScrollArea https://blog.csdn.net/u014491932/article/details/132245486          QTextEdit 是一个先

    2024年02月11日
    浏览(26)
  • Qt应用开发(基础篇)——字体选择器 QFontDialog

             QFontDialog 类继承于QDialog,是一个设计用来选择字体的对话框部件。         对话框窗口QDialog           QFontDialog 字体选择对话框,设计用来让用户选择某一种字体,一般用于文本编辑窗口、标签显示和一些需要文本输入的场景。你可以直接使用静态函数

    2024年02月10日
    浏览(38)
  • Qt应用开发(基础篇)——LCD数值类 QLCDNumber

            QLCDNumber类继承于QFrame,QFrame继承于QWidget,是Qt的一个基础小部件。         框架类QFrame介绍         QLCDNumber用来显示一个带有类似lcd数字的数字,适用于 信号灯 、 跑步机 、 体温计 、 时钟 、 电表 、 水表 、 血压计 等仪器类产品的数值显示。      

    2024年02月13日
    浏览(34)
  • Qt应用开发(基础篇)——对话框窗口 QDialog

            QDialog 类继承于QWidget,是Qt基于对话框窗口(消息窗口 QMessageBox 、颜色选择窗口 QColorDialog 、文件选择窗口 QFileDialog 等)的基类。           QDialog 窗口是顶级的窗口,一般情况下,用来当做用户短期任务(确认、输入、选择)或者和用户交流(提示、错误、警告、进

    2024年02月10日
    浏览(32)
  • Qt应用开发(基础篇)——输入对话框 QInputDialog

             QInputDialog 类继承于 QDialog ,是一个简单方便的对话框,用于从用户获取单个值。         对话框窗口 QDialog           QInputDialog输入对话框 带有一个文本标签、一个输入框和标准按钮。输入内容可以字符、数字和选项,文本标签用来告诉用户应该要输入什

    2024年02月10日
    浏览(30)
  • Qt应用开发(基础篇)——纯文本编辑窗口 QPlainTextEdit

             QPlainTextEdit 类继承于 QAbstractScrollArea , QAbstractScrollArea 继承于 QFrame ,是Qt用来显示和编辑纯文本的窗口。 滚屏区域基类 https://blog.csdn.net/u014491932/article/details/132245486?spm=1001.2014.3001.5501 框架类QFrame https://blog.csdn.net/u014491932/article/details/132188655?spm=1001.2014.3001.5501   

    2024年02月11日
    浏览(32)
  • Qt应用开发(基础篇)——文件选择对话框 QFileDialog

             QFileDialog 类继承于 QDialog ,提供了一个允许用户选择文件或目录的对话框。         对话框窗口 QDialog          QFileDialog 文件选择对话框允许用户在当前文件系统中选择一个或者多个文件或者文件路径,使用静态函数创建是很简便的方式,比如:      

    2024年02月09日
    浏览(33)
  • Qt应用开发(基础篇)——MDI窗口 QMdiArea QMdiSubWindow

             QMdiArea 类继承于QAbstractScrollArea,QAbstractScrollArea继承于QFrame,是Qt用来显示MDI窗口的部件。        滚屏区域基类 QAbstractScrollArea https://blog.csdn.net/u014491932/article/details/132245486        框架类 QFrame https://blog.csdn.net/u014491932/article/details/132188655           QMdiA

    2024年02月12日
    浏览(34)
  • Qt应用开发(基础篇)——时间微调输入框QDateTimeEdit、QDateEdit、QTimeEdit

             QAbstractSpinBox 是全部微调输入框的父类,这是一种允许用户通过点击上下箭头按钮或输入数字来调整数值的图形用户界面控件,父类提供了当前值 text 、对齐方式 align 、只读 readOnly 等通用属性和方法。在上一篇数值微调输入框中有详细介绍。          QDate

    2024年02月14日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包