Qt5 lambda表达式连接QTcpServer信号槽
来源:互联网 发布:奇异矩阵 线性相关 编辑:程序博客网 时间:2024/05/22 09:52
Problem
当有多条语句调用而又不希望写成一个单独的模块(函数或者方法)时,对于普通的方法可以写成内联形式,避免函数调用入栈、出栈等开销,也或者可以定义一段宏,不过宏没有类型检查,也没有作用对象的概念。而当这多条语句是在定义QObject::connect连接某信号的槽的实现逻辑时,除了lambda表达式,好像没有别的更好方法了。
Solution
先上一段代码,用一个简单的Qt自带的QTcpSocket和QTcpServer实现一个Tcp单机收发的功能。
头文件MainWindow.h
#ifndef MAINWINDOW_H#define MAINWINDOW_H#include <QMainWindow>#include <iostream>#include <cstdio>#include <QtNetwork/QTcpServer>#include <QtNetwork/QTcpSocket>#include <windows.h>namespace Ui {class MainWindow;}class MainWindow : public QMainWindow{ Q_OBJECTpublic: explicit MainWindow(QWidget *parent = 0); ~MainWindow();private slots: void on_BtnTcpSndData_clicked();private: Ui::MainWindow *ui; QTcpServer tcpServer; QTcpSocket socket;};#endif // MAINWINDOW_H
源文件MainWindow.cpp
#include "MainWindow.h"#include "ui_MainWindow.h"using namespace std;MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow){ connect(&tcpServer,&QTcpServer::newConnection, [&](){QTcpSocket* pSocket=tcpServer.nextPendingConnection(); connect(pSocket,&QTcpSocket::readyRead, [=](){ui->textEditTcpRcv->append(QString::fromLocal8Bit(pSocket->readAll())); });}); tcpServer.listen(QHostAddress("127.0.0.1"),8888); Sleep(500); socket.connectToHost("127.0.0.1",8888); ui->setupUi(this);}MainWindow::~MainWindow(){ delete ui;}void MainWindow::on_BtnTcpSndData_clicked(){ socket.write(ui->textEditDataToSnd->toPlainText().toLocal8Bit().data());}
注意下在pro文件中对c++11、和network进行设置。pro文件中添加如下2条语句。
QT += networkCONFIG += c++11
如上代码所示,直接在构造函数中即可实现所有的TcpSocket、TcpServer创建与连接工作,而且将Server端接收到数据的处理逻辑也写进去了。所有的逻辑都在下面这条语句。
connect(&tcpServer,&QTcpServer::newConnection, [&](){QTcpSocket* pSocket=tcpServer.nextPendingConnection(); connect(pSocket,&QTcpSocket::readyRead, [=](){ui->textEditTcpRcv->append(QString::fromLocal8Bit(pSocket->readAll())); });});
这是一个嵌套的connect连接操作。首先,如果Server端有新的连接,进入第一个lambda表达式的处理逻辑,保存当前连接的套接字,将当前套接字的准备好读的信号连接到最终处理的也即第二个lambda表达式。第二个lambda表示式中将当前套接字读取的内容显示在屏幕上。
注意tcpServer.nextPendingConnection()返回的指针是多变的,即第一次取出是指针,未有新连接,再调用些函数取出的是空指针。所以需要用一个自定义的变量来进行保存。
———————————————————————————
Appendix Qt Lambda表达式
此介绍出处http://www.aichengxu.com/view/5170676
简单来说,Lambda函数也就是一个函数,它的语法定义如下:
[capture](parameters)mutable->return-type{statement}
1.[capture]:捕捉列表。捕捉列表总是出现在Lambda函数的开始处。实际上,[]是Lambda引出符。编译器根据该引出符判断接下来的代码是否是Lambda函数。捕捉列表能够捕捉上下文中的变量以供Lambda函数使用;
2.(parameters):参数列表。与普通函数的参数列表一致。如果不需要参数传递,则可以连同括号“()”一起省略;
3.mutable:mutable修饰符。默认情况下,Lambda函数总是一个const函数,mutable可以取消其常量性。在使用该修饰符时,参数列表不可省略(即使参数为空);
4.->return-type:返回类型。用追踪返回类型形式声明函数的返回类型。我们可以在不需要返回值的时候也可以连同符号”->”一起省略。此外,在返回类型明确的情况下,也可以省略该部分,让编译器对返回类型进行推导;
5.{statement}:函数体。内容与普通函数一样,不过除了可以使用参数之外,还可以使用所有捕获的变量。
与普通函数最大的区别是,除了可以使用参数以外,Lambda函数还可以通过捕获列表访问一些上下文中的数据。具体地,捕捉列表描述了上下文中哪些数据可以被Lambda使用,以及使用方式(以值传递的方式或引用传递的方式)。语法上,在“[]”包括起来的是捕捉列表,捕捉列表由多个捕捉项组成,并以逗号分隔。捕捉列表有以下几种形式:
1.[var]表示值传递方式捕捉变量var;
2.[=]表示值传递方式捕捉所有父作用域的变量(包括this);
3.[&var]表示引用传递捕捉变量var;
4.[&]表示引用传递方式捕捉所有父作用域的变量(包括this);
5.[this]表示值传递方式捕捉当前的this指针。
上面提到了一个父作用域,也就是包含Lambda函数的语句块,说通俗点就是包含Lambda的“{}”代码块。上面的捕捉列表还可以进行组合,例如:
1.[=,&a,&b]表示以引用传递的方式捕捉变量a和b,以值传递方式捕捉其它所有变量;
2.[&,a,this]表示以值传递的方式捕捉变量a和this,引用传递方式捕捉其它所有变量。
不过值得注意的是,捕捉列表不允许变量重复传递。
——————————————————————–保持成长! :)
- Qt5 lambda表达式连接QTcpServer信号槽
- QT5 信号槽连接机制
- Qt5中使用lambda表达式
- Qt5中使用lambda表达式
- QTcpServer使用信号槽单线程方式直接处理连进来的客户端(短连接或少数据处理)
- Qt5 UI信号、槽自动连接的控件重名大坑
- Qt5信号与槽C++11风格连接简介
- Qt5 connect新语法:Lambda表达式
- QT5 信号槽
- Qt5菜鸟入门(2) 连接信号槽和信号小例子
- Qt5信号和槽机制
- Qt5信号和槽机制
- QT5之信号与槽
- Qt5.8.0信号和槽
- Qt5 信号槽新写法
- Qt5信号和槽机制
- QT5 信号槽小知识
- QTcpServer多个TcpSocket连接
- Target host is null、java.net.URISyntaxException的解决办法
- Maven学习总结(七)——eclipse中使用Maven创建Web项目
- Hive加载数据时遇到NULL数据错误的解决方法
- 异步批量加载图片
- 词频统计
- Qt5 lambda表达式连接QTcpServer信号槽
- 计算机杂谈
- cocos2dx 启动渲染过程
- 全排列-字典序
- 依赖库Underscore系列(2)--数组
- Packing data with Python
- 特征选择
- 用AFN发送字符串形式的Json数据给服务器
- 08-CoreData学习总结