zoukankan      html  css  js  c++  java
  • QT信号槽连接语法总结

    信号槽是 Qt 框架引以为豪的机制之一。

    所谓信号槽,实际就是观察者模式。当某个事件发生之后,比如,按钮检测到自己被点击了一下,它就会发出一个信号(signal)。这种触发是没有目的的,类似广播。如果有对象对这个信号感兴趣,它就会使用连接(connect)函数,意思是,将想要处理的信号和自己的一个函数(称为槽(slot))绑定来处理这个信号。也就是说,当信号发出时,被连接的槽函数会自动被回调。这就类似观察者模式:当发生了感兴趣的事件,某一个操作就会被自动触发。(这里提一句,Qt 的信号槽使用了额外的处理来实现,并不是 GoF 经典的观察者模式的实现方式。)

    信号和槽是Qt特有的信息传输机制,是Qt设计程序的重要基础,它可以让互不干扰的对象建立一种联系。

    槽的本质是类的成员函数,其参数可以是任意类型的。和普通C++成员函数几乎没有区别,它可以是虚函数;也可以被重载;可以是公有的、保护的、私有的、也可以被其他C++成员函数调用。唯一区别的是:槽可以与信号连接在一起,每当和槽连接的信号被发射的时候,就会调用这个槽

    信号与槽的连接:

     C++ Code 
    1
    2
    3
    4
    5
    6
    7
    8
     
    static QMetaObject::Connection
    connect(
        
    const QObject *sender,                          // 参数一:发送者
        const QMetaMethod &signal,                      // 参数二:信号
        const QObject *receiver,                        // 参数三:接收者
        const QMetaMethod &method,                      // 参数四:槽
        Qt::ConnectionType type = Qt::AutoConnection);  // 参数五:连接类型

    注意:信号槽要求信号和槽的参数一致,所谓一致,是参数类型一致。如果不一致,允许的情况是,槽函数的参数可以比信号的少,即便如此,槽函数存在的那些参数的顺序也必须和信号的前面几个一致起来。这是因为,你可以在槽函数中选择忽略信号传来的数据(也就是槽函数的参数比信号的少),但是不能说信号根本没有这个数据,你就要在槽函数中使用(就是槽函数的参数比信号的多,这是不允许的)。

    信号槽的书写方式:

    • Qt4的书写方式

    QPushButton* button = new QPushButton("Quit");

    connect(button, SIGNAL(clicked()), &a, SLOT(quit()));

    这种写法没有编译错误,而是在运行时给出错误,无疑会增加程序的不稳定性。

    只有在 Debug 模式下运行时才会提示槽函数不存在,Release 模式下运行时不会给予任何错误提示。

    • Qt5的书写方式

    QPushButton button("Quit");

    QObject::connect(&button, &QPushButton::clicked, &app,&QApplication::quit);

    • C++11新方式: Lambda表达式,需要再Pro项目文件中加入 CONFIG += C++ 11

    QPushButton* button = new QPushButton("Quit");

    connect(button, SIGNAL(clicked()),[=](QString str){

                     qDebug() << str;});

    关于Lambda表达式的知识

    简单地说,Lambda表达式就是匿名函数。

    以一对方括号[]开始,称为Lambda表达式的引入符。

    引入符后面可以添加Lambda表达式的返回值类型。

    接着是参数列表,最后是Lambda表达式的函数体。

    引入符描述函数体如何“获得”外部变量!

    所谓“外部变量”指的是函数体以外的变量,这些变量需要在引入符可见的作用域中有定义。

    Lambda表达式构成图解:

    • Capture clause: 捕获子句
    • Parameter list: 参数列表 可选
    • Mutable specification 可选
    • Exception specification 可选
    • Return type: 返回类型 可选
    • Lambda Body

    需要注意的一点:在进行信号槽绑定时,如果有重载,需要对成员函数进行类型转换,可以使用 C++ 的 static_cast 类型转换(编译时进行语法检查),也可以使用传统的 C 语言的强制类型转换(编译时不进行语法检查,运行时才检查),或者 C++11 的 QOverload::of,C++14 的 qOverload:

     C++ Code 
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
     
    QComboBox *comboBox = new QComboBox();
    comboBox->addItem(
    "Michael");
    comboBox->addItem(
    "Kobe");
    comboBox->addItem(
    "James");
    comboBox->show();

    // [1]
    QObject::connect(comboBox,
                     
    static_cast<void (QComboBox::*)(int)>(&QComboBox::activated),
                     [](
    int index)
    {
        qDebug() << index;
    });

    // [2]
    QObject::connect(comboBox,
                     
    static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::activated),
                     [](
    const QString &text)
    {
        qDebug() << text;
    });

    // [3]: QOverload<> 里面是参数列表,of() 里面是成员函数地址
    QObject::connect(comboBox,
                     QOverload<
    const QString &>::of(&QComboBox::activated),
                     [](
    const QString &text)
    {
        qDebug() << text;
    });
  • 相关阅读:
    Java求区间连续最大和的三种解法(含输出起始位置)
    Java批量操作和遍历文件程序收集
    FastJson序列化部分字段的方法
    Spring源码之一步步拓展实现spring-mybatis
    Spring源码之BeanFactoryPostProcessor的执行顺序
    Classpath entry points to a non-existent location:D:libjavajdk8jrelibextaccess-bridge-32.jar
    编译Spring源码省心小贴士
    (转)HttpServletResquest对象
    (转)ServletConfig与ServletContext
    Oracle复习(复习精简版v1.0)
  • 原文地址:https://www.cnblogs.com/MakeView660/p/11941653.html
Copyright © 2011-2022 走看看