网络编程TCP/IP/UDP+Http和JSON解析+qt事件软键盘
原文:https://blog.csdn.net/m0_45463480/article/details/124049417
网络编程+Http和JSON解析+qt事件软键盘
- 第一章 QT中的网络编程
-
- 【1】涉及到的类
- 【2】tcp协议的流程
-
- 【2.1】服务器的流程 socket--》bind--》listen--》accept--》send/recv--》close
- 【2.2】客户端的流程 socket--》bind--》connect--》send/recv--》close
- 【3】多客户端连接同一个服务器
- 第二章 QT中的udp通信
-
- 【1】涉及到的类
- 【2】udp流程
-
- 【2.1】创建QUdpSocket对象
- 【2.2】绑定
- 【2.3】收发信息
- 第三章 QT中的http协议
-
- 【1】http协议的原理
- 【2】QT提供的http有关的类和方法
-
- 【2.1】函数和类
- 【2.2】创建QNetworkRequest请求
- 【2.3】发送http请求
- 【2.4】读取服务器回复的应答信息
- 【3】举例使用http协议
- 第四章 JSON数据解析
-
- 【1】什么是JSON数据
- 【2】如何解析json数据(剥洋葱,从外到内,一层层剥皮)
- 【3】解析json数据的一般思路:
- 第五章 QT中的事件,事件实现软键盘
-
- 【1】什么是事件
- 【2】QT事件产生的流程
- 【3】常用的事件类型和处理函数
- 【4】利用移动事件的处理函数实现
- 第六章 用QT按键事件实现软键盘
-
- 【1】软键盘实现步骤
- 【2】软键盘实现函数
- 【3】QT编译最常见的问题
- 第七章 代码编写,加深印象
-
- 【1】tcp单向通信源码【半双工】
-
- 【1.1】tcpclient客户端
-
- 【1.1.1】tcpclient.pro
- 【1.1.2】main.c
- 【1.1.3】MainWindow.h
- 【1.1.4】 MainWindow.c
- 【1.1.4】 MainWindow.ui界面设计
- 【1.2】tcpserver服务器
-
- 【1.2.1】main.cpp
- 【1.2.2】mainwindow.h
- 【1.2.3】mainwindow.cpp
- 【1.2.4】mainwindow.ui
- 【2】tcp双向通信源码【全双工】
-
- 【2.1】tcpclient客户端
-
- 【2.1.1】main.cpp
- 【2.1.2】mainwindow.h
- 【2.1.3】mainwindow.cpp
- 【2.1.4】mainwindow.ui
- 【2.2】tcpserver服务器
-
- 【2.2.1】main.cpp
- 【2.2.2】mainwindow.h
- 【2.2.3】mainwindow.cpp
- 【2.2.4】mainwindow.ui
- 【3】http获取天气信息,解析json数据源码
-
- 【3.1】main.cpp
- 【3.2】mainwindow.h
- 【3.3】mainwindow.cpp
- 【3.4】mainwindow.ui
- 【4】事件实现软键盘源码
-
- 【4.1】main.c
- 【4.2】loginwin.h
- 【4.3】loginwin.cpp
- 【4.4】loginwin.ui
- 【4.5】mybutton.h
- 【4.6】mybutton.cpp
- 【4.7】mysolfkey.h
- 【4.8】mysolfkey.cpp
- 【4.9】mysolfkey.ui
- 【5】事件流程重写了事件处理函数
-
- 【5.1】main.cpp
- 【5.2】mainwindow.cpp
- 【5.3】mainwindow.h
- 【5.4】mainwindow.ui
- 【6】所有源码分享
- 第八章 往期内容回顾
第一章 QT中的网络编程
【1】涉及到的类
QTcpServer类 --》表示tcp服务器
QTcpSocket类 --》表示tcp套接字
添加新的库-
绝大部分类都是在 core gui widgets这三个库里面(QT工程默认也是添加这三个库)-
有些类属于其它的内库,需要主动在pro文件中添加新的内库-
QT += core gui network //添加了network这个新的库
【2】tcp协议的流程
?imageUrl=https%3A%2F%2Fimg-blog.csdnimg.cn%2F5d883e11b44e450c9e87586cae8ad625.png%3Fx-oss-process%3Dimage%2Fwatermark%2Ctype_d3F5LXplbmhlaQ%2Cshadow_50%2Ctext_Q1NETiBA57qi5a6i55m95bi9%2Csize_20%2Ccolor_FFFFFF%2Ct_70%2Cg_se%2Cx_16%23pic_center&valid=false)
【2.1】服务器的流程 socket–》bind–》listen–》accept–》send/recv–》close
第一步:创建QTcpServer的对象
QTcpServer(QObject *parent = nullptr)
第二步:绑定和监听
bool QTcpServer::listen(const QHostAddress &address = QHostAddress::Any, quint16 port 加粗样式= 0)
参数: address --》你要绑定的ip地址
QHostAddress(const QString &address) //address是你的ip地址
port --》你要绑定的端口号
第三步(重点):如果有新的客户端连接服务器,QTcpServer的对象会自动触发:
[signal] void QTcpServer::newConnection();
程序员关联该信号,在槽函数中实现接下来的逻辑-
在槽函数中实现的逻辑如下:
调用QTcpSocket *QTcpServer::nextPendingConnection()产生新的套接字
返回值:QTcpSocket 就是产生的新套接字
第四步(重点):利用刚才第三步产生的套接字去跟对应的客户端通信–》收发信息
发送信息: qint64 QIODevice::write(const QByteArray &byteArray)
接收信息(要注意,不能直接调用read/readAll去接收信息):QByteArray QIODevice::read(qint64 maxSize)
QByteArray QIODevice::readAll()
注意,注意,注意:如果对方有发送信息过来,QTcpSocket的对象会产生:
[signal] void QIODevice::readyRead()信号
程序员关联该信号,在槽函数中去接收信息即可-
第五步:关闭
close();
【2.2】客户端的流程 socket–》bind–》connect–》send/recv–》close
第一步:创建QTcpSocket的对象
QTcpSocket(QObject *parent = nullptr)
第二步:绑定自己的ip和端口号
bool QAbstractSocket::bind(const QHostAddress &address, quint16 port = 0)
参数: address --》你要绑定的ip地址
QHostAddress(const QString &address) //address是你的ip地址
port --》你要绑定的端口号
第三步:连接服务器
void QAbstractSocket::connectToHost(const QHostAddress &address, quint16 port)
参数: address --》 你要连接的服务器的ip地址
QHostAddress(const QString &address)
port --》服务器的端口号
第四步:跟服务器通信–》收发信息
发送信息: qint64 QIODevice::write(const QByteArray &byteArray)
接收信息(要注意,不能直接调用read/readAll去接收信息):QByteArray QIODevice::read(qint64 maxSize)
=QByteArray QIODevice::readAll()
注意,注意,注意:如果对方有发送信息过来,QTcpSocket的对象会产生
[signal] void QIODevice::readyRead()信号
程序员关联该信号,在槽函数中去接收信息即可-
第五步:关闭
close();
【3】多客户端连接同一个服务器
(1)获取连接成功的客户端/服务器的ip和端口号
QHostAddress QAbstractSocket::peerAddress() const
返回值:连接成功的客户端/服务器的ip地址
QString QHostAddress::toString() const //把返回值QHostAddress对象转换成我们熟悉的字符串格式ip地址
quint16 QAbstractSocket::peerPort() const
返回值:连接成功的客户端/服务器的端口号
4.判断客户端/服务器是否断开连接
[signal] void QAbstractSocket::disconnected()
//断开连接会自动触发该信号,程序员在槽函数中写代码判断
第二章 QT中的udp通信
【1】涉及到的类
QUdpSocket
【2】udp流程
发送端
【2.1】创建QUdpSocket对象
QUdpSocket::QUdpSocket(QObject *parent = nullptr)
【2.2】绑定
bool QAbstractSocket::bind(const QHostAddress &address, quint16 port = 0)
参数: address --》你要绑定的ip地址
QHostAddress(const QString &address) //address是你的ip地址
port --》你要绑定的端口号
【2.3】收发信息
发送:qint64 QUdpSocket::writeDatagram(const QByteArray &datagram, const QHostAddress &host, quint16 port)
返回值:发送的字节数
参数:datagram --》存放你要发送的内容
host --》对方的ip
port --》对方的端口号
接收:qint64 QUdpSocket::readDatagram(char *data, qint64 maxSize)
返回值:成功收到的字节数
参数:data --》存放接收的内容
maxSize --》你打算接收多少字节的数据
注意,注意,注意:如果对方有发送信息过来,QUdpSocket的对象会产生
[signal] void QIODevice::readyRead()信号
程序员关联该信号,在槽函数中去接收信息即可
第三章 QT中的http协议
?imageUrl=https%3A%2F%2Fimg-blog.csdnimg.cn%2F0343ba6ad7e0490c8776c084701e2309.png%3Fx-oss-process%3Dimage%2Fwatermark%2Ctype_d3F5LXplbmhlaQ%2Cshadow_50%2Ctext_Q1NETiBA57qi5a6i55m95bi9%2Csize_20%2Ccolor_FFFFFF%2Ct_70%2Cg_se%2Cx_16%23pic_center&valid=false)
【1】http协议的原理
学习前端的同学需要重点掌握的一种应用层的通信协议
http协议的底层就是tcp
比如:张同学通过360浏览器登录QQ的官方网站-
360浏览器:tcp客户端-
QQ的官网服务器: tcp服务器-
你在浏览器中输入:www.qq.com(域名或者URL地址) --》会被浏览器解析成QQ服务器的ip地址和端口号
【2】QT提供的http有关的类和方法
【2.1】函数和类
QNetworkRequest --》表示http请求
QNetworkAccessManager --》管理http请求(发送http请求)
QNetworkReply --》表示http的应答
【2.2】创建QNetworkRequest请求
QNetworkRequest(const QUrl &url)
参数:url --》你要访问的网址
QUrl(const QString &url) //url就是网址www.csdn.net
【2.3】发送http请求
QNetworkReply *QNetworkAccessManager::get(const QNetworkRequest &request)
参数:request --》你要发送的http请求
【2.4】读取服务器回复的应答信息
关键点:我如何得知服务器真的回复了应答信息 给我????-
方法:如果服务器应答成功QNetworkAccessManager对象会自动触发
[signal] void QNetworkAccessManager::finished(QNetworkReply *reply)信号
程序员主动关联该信号,在槽函数里面读取应答信息即可
QNetworkReply类中: QByteArray QIODevice::readAll() 读取应答信息
【3】举例使用http协议
例子一:http请求下载网络上的图片
bool QPixmap::loadFromData(const QByteArray &data)
参数:data --》从网上下载的图片原始数据
注意:图片的网址需要把https中的s去掉
https 有加密
http 没有加密
例子二:http请求获取网络上的天气预报-
http://www.weather.com.cn/data/cityinfo/101010100.html
第四章 JSON数据解析
?imageUrl=https%3A%2F%2Fimg-blog.csdnimg.cn%2F18f54ef292704086a15129f91c0ade0c.png%3Fx-oss-process%3Dimage%2Fwatermark%2Ctype_d3F5LXplbmhlaQ%2Cshadow_50%2Ctext_Q1NETiBA57qi5a6i55m95bi9%2Csize_20%2Ccolor_FFFFFF%2Ct_70%2Cg_se%2Cx_16%23pic_center&valid=false)
【1】什么是JSON数据
json数据:一种人为制定的数据格式,在计算机前端开发中经常使用这种格式的数据,保存信息很方便-
json数据只能由数组,对象,键值对三种构成-
对象:用{}来表示,可以嵌套其他两种数据 { {},{}} {键值对} {[数组]} {{},[]}-
数组:用[]来表示,数组里面只能存放相同类型的数据 [1,2,3] [{},{},{}] [键值对,键值对,键值对]-
键值对:用键:值表示, 键只能是字符串,值可以是任意合法类型-
星期一:1-
星期二:2-
张三:123456-
李四:789456
【2】如何解析json数据(剥洋葱,从外到内,一层层剥皮)
json数据在解析之前,程序员必须要提前知道json数据的构成,否则无法解析-
QT提供了如下几个类帮助大家解析json数据:
QJsonDocument --》把json数据标准化存储
QJsonObject --》对象
QJsonArray --》数组
QJsonValue --》值
QJsonParseError --》保存出错信息
【3】解析json数据的一般思路:
第一步:把json数据标准化存储
[static] QJsonDocument QJsonDocument::fromJson(const QByteArray &json, QJsonParseError *error = Q_NULLPTR)
返回值:QJsonDocument对象存放标准化之后的json数据
参数:json --》你要存储的原始json数据
error --》存放出错信息
第二步:严格按照你看到的json数据的结构一步步解析json数据(从整体到局部,一层层剥洋葱)
QJsonObject QJsonDocument::object() const //获取json数据中的对象
QJsonArray QJsonDocument::array() const //获取json数据中的数组
QJsonValue QJsonObject::value(const QString &key) const //通过键得到对应的值
返回值:跟键对应的值
参数:key --》键
QJsonObject QJsonValue::toObject() const //把键值对中的值进行转换,转换成对象
int QJsonValue::toInt() const //把键值对中的值进行转换,转换成整数
QJsonArray QJsonValue::toArray() const //把键值对中的值进行转换,转换成数组
总结:QJsonValue类中提供了大量的toxxxxx()方法,原因是键值对中的值可以是任意合法的数据类型,需要我们去转换
第五章 QT中的事件,事件实现软键盘
?imageUrl=https%3A%2F%2Fimg-blog.csdnimg.cn%2Fff363dc40b124df8810a060fc1856562.png%3Fx-oss-process%3Dimage%2Fwatermark%2Ctype_d3F5LXplbmhlaQ%2Cshadow_50%2Ctext_Q1NETiBA57qi5a6i55m95bi9%2Csize_20%2Ccolor_FFFFFF%2Ct_70%2Cg_se%2Cx_16%23pic_center&valid=false)
【1】什么是事件
用户对于QT程序所做的一切行为动作–>都称之为事件-
比如:用户用鼠标把窗口拉大,拉小 --》窗口大小改变事件-
用户用鼠标拖动窗口 --》移动事件-
用户按了键盘 --》按键事件-
用户鼠标点击窗口 --》鼠标事件-
用户关闭窗口 --》关闭事件
QEvent: 所有事件类的父类
【2】QT事件产生的流程
详情见截图
【3】常用的事件类型和处理函数
事件类型 枚举值 事件处理函数
QCloseEvent --》 QEvent::Close --》void QWidget::closeEvent(QCloseEvent *event) //关闭窗口对应的处理函数
QFocusEvent --》 QEvent::FocusIn --》void QWidget::focusInEvent(QFocusEvent *event) //键盘输入光标进入对应的处理函数
QMouseEvent --》 QEvent::MouseButtonDblClick --》void QWidget::mouseDoubleClickEvent(QMouseEvent *event) //鼠标双击事件的处理函数
QEvent::MouseButtonPress void QWidget::mouseMoveEvent(QMouseEvent *event) //鼠标移动对应的处理函数
QEvent::MouseButtonRelease void QWidget::mousePressEvent(QMouseEvent *event) //鼠标按下对应的处理函数
QEvent::MouseMove void QWidget::mouseReleaseEvent(QMouseEvent *event) //鼠标松开对应的处理函数
QKeyEvent --》 QEvent::KeyPress --》 void QWidget::keyPressEvent(QKeyEvent *event) //按键按下去
QEvent::KeyRelease void QWidget::keyReleaseEvent(QKeyEvent *event) //按键松开
int QKeyEvent::key() //获取按键的键值(QT助手有详细介绍)
QString QKeyEvent::text() //返回按键的字面值
QMoveEvent--》 QEvent::Move --》 void QWidget::moveEvent(QMoveEvent *event) //移动窗口对应的处理函数
【4】利用移动事件的处理函数实现
当我用鼠标拖动窗口的时候,窗口背景色的颜色会随机变换-
QT中产生随机数
int qrand() --》类似rand()
void qsrand(uint seed) --》类似srand()
第六章 用QT按键事件实现软键盘
【1】软键盘实现步骤
第一步: 【设计好软键盘的ui(模板选择QWidget,原因是软键盘等会要嵌套到主窗口中)】
在ui把按钮的focusPolicy属性设置成Nofocus
第二步:在主窗口中拖一个QWidget容器过来,然后右键点击QWidget,选择提升为你刚才创建的那个软键盘类型-
第三步:写代码实现软键盘可以正常使用
思路一:传统思路,利用信号与槽实现软键盘的功能 (把所有的信号关联槽函数,一个个去判断)-
思路二:使用按键事件来实现软键盘的功能
【2】软键盘实现函数
在QT工程中新建一个自定义的按钮类,继承QPushButton,然后右键把你的软键盘上所有的按钮都提升为这个类
QKeyEvent::QKeyEvent(QEvent::Type type, int key, Qt::KeyboardModifiers modifiers, const QString &text = QString())
参数: type --》事件类型 QEvent::KeyPress
key --》按键的键值 字母的键值就是大写字面的ASCII码值
modifiers --》有没有使用组合键
Qt::NoModifier 没有使用组合键
Qt::ShiftModifier 使用了shift
Qt::ControlModifier 使用了ctrl
Qt::AltModifier 使用了alt
text --》按键的字面值
获取鼠标光标停留的组件(鼠标光标停留在哪个组件上,该函数就返回这个组件的地址指针)
[static] QWidget *QApplication::focusWidget()
返回值:鼠标停留的组件地址
【3】QT编译最常见的问题
?imageUrl=https%3A%2F%2Fimg-blog.csdnimg.cn%2F7a3ff8bb9276404d974b9d4f8104c44c.png%3Fx-oss-process%3Dimage%2Fwatermark%2Ctype_d3F5LXplbmhlaQ%2Cshadow_50%2Ctext_Q1NETiBA57qi5a6i55m95bi9%2Csize_20%2Ccolor_FFFFFF%2Ct_70%2Cg_se%2Cx_16%23pic_center&valid=false)
第七章 代码编写,加深印象
【1】tcp单向通信源码【半双工】
【1.1】tcpclient客户端
【1.1.1】tcpclient.pro
QT += core gui network
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += c++11
The following define makes your compiler emit warnings if you use
any Qt feature that has been marked deprecated (the exact warnings
depend on your compiler). Please consult the documentation of the
deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
You can also make your code fail to compile if it uses deprecated APIs.
In order to do so, uncomment the following line.
You can also select to disable deprecated APIs only up to a certain version of Qt.
DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES +=
main.cpp
mainwindow.cpp
HEADERS +=
mainwindow.h
FORMS +=
mainwindow.ui
Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
【1.1.2】main.c
include "mainwindow.h"
include
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
【1.1.3】MainWindow.h
ifndef MAINWINDOW_H
define MAINWINDOW_H
include
include
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void on_linkbt_clicked();
void on_sendbt_clicked();
private:
Ui::MainWindow *ui;
QTcpSocket *mysock;
};
#endif // MAINWINDOW_H
【1.1.4】 MainWindow.c
include "mainwindow.h"
include "ui_mainwindow.h"
include
- MainWindow::MainWindow(QWidget *parent)
- QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
//设置窗口标题
setWindowTitle("我是客户端");
//初始化套接字对象
mysock=new QTcpSocket(this);
//绑定客户端自己的ip和端口号
mysock->bind(QHostAddress("192.168.24.2"),20000);
}
MainWindow::~MainWindow()
{
delete ui;
}
//连接服务器
void MainWindow::on_linkbt_clicked()
{
//获取输入的服务器ip和端口号
QString str1=ui->iple->text();
QString str2=ui->portle->text();
//连接服务器
mysock->connectToHost(QHostAddress(str1),str2.toInt());
}
//发送信息
void MainWindow::on_sendbt_clicked()
{
//获取客户端输入的信息
QString buf=ui->textEdit_2->toPlainText();
//发送给服务器
mysock->write(buf.toUtf8());
}
【1.1.4】 MainWindow.ui界面设计
把这段代码赋值进你创建的ui文件,编译之后会自动生成图标的
ui界面设计:-
?imageUrl=https%3A%2F%2Fimg-blog.csdnimg.cn%2F123e7a5cce6c4fafa46374aa01605ff4.png%3Fx-oss-process%3Dimage%2Fwatermark%2Ctype_d3F5LXplbmhlaQ%2Cshadow_50%2Ctext_Q1NETiBA57qi5a6i55m95bi9%2Csize_20%2Ccolor_FFFFFF%2Ct_70%2Cg_se%2Cx_16&valid=false)
【1.2】tcpserver服务器
【1.2.1】main.cpp
include "mainwindow.h"
include
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
【1.2.2】mainwindow.h
ifndef MAINWINDOW_H
define MAINWINDOW_H
include
include
include
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void newClientLink();
void recvclientmsg();
private:
Ui::MainWindow *ui;
QTcpServer *myserver;
QTcpSocket *sock;
};
#endif // MAINWINDOW_H
【1.2.3】mainwindow.cpp
include "mainwindow.h"
include "ui_mainwindow.h"
include
include
- MainWindow::MainWindow(QWidget *parent)
- QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
//设置标题
setWindowTitle("我是服务器");
//初始化QTcpServer的对象
myserver=new QTcpServer(this);
//绑定和监听
myserver->listen(QHostAddress("192.168.24.2"),10000);
//关联newConnection信号
connect(myserver,SIGNAL(newConnection()),this,SLOT(newClientLink()));
}
MainWindow::~MainWindow()
{
delete ui;
}
//如果有新的客户端连接成功,该槽函数会被自动调用
void MainWindow::newClientLink()
{
qDebug()<<"有新的客户端连接成功了";
//产生新的套接字
sock=myserver->nextPendingConnection();
//反面教材,直接接收信息
//QByteArray buf=sock->readAll(); 错误错误错误
//关联readyRead()信号
connect(sock,SIGNAL(readyRead()),this,SLOT(recvclientmsg()));
}
//专门用来接收某个客户端信息的槽函数
void MainWindow::recvclientmsg()
{
//接收信息
QByteArray buf=sock->readAll();
//在文本编辑框中显示出来
//ui->textEdit->setText(buf); setText会自动清空覆盖原来显示的信息
ui->textEdit->append(buf);
}
【1.2.4】mainwindow.ui
ui界面设计-
?imageUrl=https%3A%2F%2Fimg-blog.csdnimg.cn%2Fd6a36099f28f44dbb386ee7c8bd0ff6f.png%3Fx-oss-process%3Dimage%2Fwatermark%2Ctype_d3F5LXplbmhlaQ%2Cshadow_50%2Ctext_Q1NETiBA57qi5a6i55m95bi9%2Csize_20%2Ccolor_FFFFFF%2Ct_70%2Cg_se%2Cx_16&valid=false)
【2】tcp双向通信源码【全双工】
【2.1】tcpclient客户端
【2.1.1】main.cpp
include "mainwindow.h"
include
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
【2.1.2】mainwindow.h
ifndef MAINWINDOW_H
define MAINWINDOW_H
include
include
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void on_linkbt_clicked();
void on_sendbt_clicked();
void recvservermsg();
private:
Ui::MainWindow *ui;
QTcpSocket *mysock;
};
#endif // MAINWINDOW_H
【2.1.3】mainwindow.cpp
include "mainwindow.h"
include "ui_mainwindow.h"
include
- MainWindow::MainWindow(QWidget *parent)
- QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
//设置窗口标题
setWindowTitle("我是客户端");
//初始化套接字对象
mysock=new QTcpSocket(this);
//绑定客户端自己的ip和端口号
mysock->bind(QHostAddress("192.168.24.2"),20000);
//关联readyRead()信号
connect(mysock,SIGNAL(readyRead()),this,SLOT(recvservermsg()));
}
MainWindow::~MainWindow()
{
delete ui;
}
//连接服务器
void MainWindow::on_linkbt_clicked()
{
//获取输入的服务器ip和端口号
QString str1=ui->iple->text();
QString str2=ui->portle->text();
//连接服务器
mysock->connectToHost(QHostAddress(str1),str2.toInt());
}
//发送信息
void MainWindow::on_sendbt_clicked()
{
//获取客户端输入的信息
QString buf=ui->textEdit_2->toPlainText();
//发送给服务器
mysock->write(buf.toUtf8());
}
//专门接收服务器发送过来的信息
void MainWindow::recvservermsg()
{
QByteArray buf=mysock->readAll();
//在文本编辑框中显示出来
ui->textEdit->append(buf);
}
【2.1.4】mainwindow.ui
界面设计-
?imageUrl=https%3A%2F%2Fimg-blog.csdnimg.cn%2F14a1149c11e1431d95488fc83690d50d.png%3Fx-oss-process%3Dimage%2Fwatermark%2Ctype_d3F5LXplbmhlaQ%2Cshadow_50%2Ctext_Q1NETiBA57qi5a6i55m95bi9%2Csize_20%2Ccolor_FFFFFF%2Ct_70%2Cg_se%2Cx_16&valid=false)
【2.2】tcpserver服务器
【2.2.1】main.cpp
include "mainwindow.h"
include
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
【2.2.2】mainwindow.h
ifndef MAINWINDOW_H
define MAINWINDOW_H
include
include
include
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void newClientLink();
void recvclientmsg();
void on_sendbt_clicked();
private:
Ui::MainWindow *ui;
QTcpServer *myserver;
QTcpSocket *sock;
};
#endif // MAINWINDOW_H
【2.2.3】mainwindow.cpp
include "mainwindow.h"
include "ui_mainwindow.h"
include
include
- MainWindow::MainWindow(QWidget *parent)
- QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
//设置标题
setWindowTitle("我是服务器");
//初始化QTcpServer的对象
myserver=new QTcpServer(this);
//绑定和监听
myserver->listen(QHostAddress("192.168.24.2"),10000);
//关联newConnection信号
connect(myserver,SIGNAL(newConnection()),this,SLOT(newClientLink()));
}
MainWindow::~MainWindow()
{
delete ui;
}
//如果有新的客户端连接成功,该槽函数会被自动调用
void MainWindow::newClientLink()
{
qDebug()<<"有新的客户端连接成功了";
//产生新的套接字
sock=myserver->nextPendingConnection();
//反面教材,直接接收信息
//QByteArray buf=sock->readAll(); 错误错误错误
//关联readyRead()信号
connect(sock,SIGNAL(readyRead()),this,SLOT(recvclientmsg()));
}
//专门用来接收某个客户端信息的槽函数
void MainWindow::recvclientmsg()
{
//接收信息
QByteArray buf=sock->readAll();
//在文本编辑框中显示出来
//ui->textEdit->setText(buf); setText会自动清空覆盖原来显示的信息
ui->textEdit->append(buf); //append会追加信息显示,不会覆盖之前显示的信息
}
//发送信息给客户端
void MainWindow::on_sendbt_clicked()
{
//获取文本编辑框中输入的内容
QString str=ui->textEdit_2->toPlainText();
//发送给客户端
sock->write(str.toUtf8());
}
【2.2.4】mainwindow.ui
界面设计-
?imageUrl=https%3A%2F%2Fimg-blog.csdnimg.cn%2Fc0f7191f4de845269482e8bb46e46ca5.png%3Fx-oss-process%3Dimage%2Fwatermark%2Ctype_d3F5LXplbmhlaQ%2Cshadow_50%2Ctext_Q1NETiBA57qi5a6i55m95bi9%2Csize_20%2Ccolor_FFFFFF%2Ct_70%2Cg_se%2Cx_16&valid=false)
【3】http获取天气信息,解析json数据源码
【3.1】main.cpp
include "mainwindow.h"
include
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
【3.2】mainwindow.h
ifndef MAINWINDOW_H
define MAINWINDOW_H
include
include
include
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void on_pushButton_clicked();
void recvhttp(QNetworkReply *);
private:
Ui::MainWindow *ui;
QNetworkAccessManager manager;
};
#endif // MAINWINDOW_H
【3.3】mainwindow.cpp
include "mainwindow.h"
include "ui_mainwindow.h"
include
include
include
include
include
include
include
include
- MainWindow::MainWindow(QWidget *parent)
- QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
//关联finished信号
connect(&manager,SIGNAL(finished(QNetworkReply *)),this,SLOT(recvhttp(QNetworkReply *)));
}
MainWindow::~MainWindow()
{
delete ui;
}
//获取天气预报的按钮
void MainWindow::on_pushButton_clicked()
{
//获取输入框中的网址
QString str=ui->lineEdit->text();
QUrl url(str);
//创建http请求
QNetworkRequest req(url);
//发送该请求
manager.get(req);
}
//接收服务器回复的应答信息
void MainWindow::recvhttp(QNetworkReply *reply)
{
//读取http应答信息
QByteArray buf=reply->readAll();
//由于我现在是从网上获取天气预报信息,buf中的数据就是天气预报数据
// ui->textEdit->setText(buf);
//天气预报数据是json格式,我来解析一下
//把获取的json数据标准化存储
QJsonParseError myerr;
QJsonDocument mydoc=QJsonDocument::fromJson(buf,&myerr);
//剥洋葱
//获取最外面的对象
QJsonObject obj=mydoc.object();
//obj存放的就是"weatherinfo":{"city":"北京","cityid":"101010100","temp1":"18℃","temp2":"31℃","weather":"多云转阴","img1":"n1.gif","img2":"d2.gif","ptime":"18:00"}
//继续获取键值对中的键和值
QJsonValue val=obj.value("weatherinfo");
//val存放的就是{"city":"北京","cityid":"101010100","temp1":"18℃","temp2":"31℃","weather":"多云转阴","img1":"n1.gif","img2":"d2.gif","ptime":"18:00"}
QJsonObject obj1=val.toObject();
//obj1存放的就是"city":"北京","cityid":"101010100","temp1":"18℃","temp2":"31℃","weather":"多云转阴","img1":"n1.gif","img2":"d2.gif","ptime":"18:00"
QJsonValue val1=obj1.value("city");
qDebug()<<val1.toString();
QJsonValue val2=obj1.value("temp1");
qDebug()<<val2.toString();
QJsonValue val3=obj1.value("temp2");
qDebug()<<val3.toString();
}
【3.4】mainwindow.ui
界面设计:-
?imageUrl=https%3A%2F%2Fimg-blog.csdnimg.cn%2F42f7d0b3d6c9466bb21790312d419657.png%3Fx-oss-process%3Dimage%2Fwatermark%2Ctype_d3F5LXplbmhlaQ%2Cshadow_50%2Ctext_Q1NETiBA57qi5a6i55m95bi9%2Csize_20%2Ccolor_FFFFFF%2Ct_70%2Cg_se%2Cx_16&valid=false)
【4】事件实现软键盘源码
这里有多个界面,是因为需要多个界面之间跳转,玩过手机的都知道,划过来划过去,其实就是创建了Qt设计师界面,相当于一个类,创建方法:-
?imageUrl=https%3A%2F%2Fimg-blog.csdnimg.cn%2F271d2480a707400896e168e653ffdeba.png%3Fx-oss-process%3Dimage%2Fwatermark%2Ctype_d3F5LXplbmhlaQ%2Cshadow_50%2Ctext_Q1NETiBA57qi5a6i55m95bi9%2Csize_20%2Ccolor_FFFFFF%2Ct_70%2Cg_se%2Cx_16&valid=false)
【4.1】main.c
include "loginwin.h"
include
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
loginwin w;
w.show();
return a.exec();
}
【4.2】loginwin.h
ifndef LOGINWIN_H
define LOGINWIN_H
include
QT_BEGIN_NAMESPACE
namespace Ui { class loginwin; }
QT_END_NAMESPACE
class loginwin : public QMainWindow
{
Q_OBJECT
public:
loginwin(QWidget *parent = nullptr);
~loginwin();
private:
Ui::loginwin *ui;
};
#endif // LOGINWIN_H
【4.3】loginwin.cpp
include "loginwin.h"
include "ui_loginwin.h"
- loginwin::loginwin(QWidget *parent)
- QMainWindow(parent)
, ui(new Ui::loginwin)
{
ui->setupUi(this);
}
loginwin::~loginwin()
{
delete ui;
}
【4.4】loginwin.ui
设计界面-
?imageUrl=https%3A%2F%2Fimg-blog.csdnimg.cn%2Fcb8f801a0f1b4c658f119a748527dab2.png%3Fx-oss-process%3Dimage%2Fwatermark%2Ctype_d3F5LXplbmhlaQ%2Cshadow_50%2Ctext_Q1NETiBA57qi5a6i55m95bi9%2Csize_20%2Ccolor_FFFFFF%2Ct_70%2Cg_se%2Cx_16&valid=false)
【4.5】mybutton.h
ifndef MYBUTTON_H
define MYBUTTON_H
include
class mybutton : public QPushButton
{
Q_OBJECT
public:
explicit mybutton(QWidget *parent = nullptr);
private slots:
void fun();
signals:
};
endif // MYBUTTON_H
【4.6】mybutton.cpp
include "mybutton.h"
include
include
include
include
mybutton::mybutton(QWidget *parent) : QPushButton(parent)
{
//关联clicked信号和自定义的槽函数
connect(this,SIGNAL(clicked()),this,SLOT(fun()));
}
void mybutton::fun()
{
//qDebug()<<"你点击软键盘上任何按钮,我都会被调用";
//获取信号的发送者
QObject *obj=sender();
mybutton *bt=qobject_cast<mybutton *>(obj);
//获取按钮的字面信息
QString str=bt->text(); // 'a'-32
int key=str.toInt()-32;
//定义一个按键事件
QKeyEvent *keyevent=new QKeyEvent(QEvent::KeyPress,key,Qt::NoModifier,str);
//把这个按键事件发送出去
return QCoreApplication::postEvent(QApplication::focusWidget(),keyevent);
}
【4.7】mysolfkey.h
ifndef MYSOLFKEY_H
define MYSOLFKEY_H
include
namespace Ui {
class mysolfkey;
}
class mysolfkey : public QWidget
{
Q_OBJECT
public:
explicit mysolfkey(QWidget *parent = nullptr);
~mysolfkey();
private:
Ui::mysolfkey *ui;
};
endif // MYSOLFKEY_H
【4.8】mysolfkey.cpp
include "mysolfkey.h"
include "ui_mysolfkey.h"
mysolfkey::mysolfkey(QWidget *parent) :
QWidget(parent),
ui(new Ui::mysolfkey)
{
ui->setupUi(this);
}
mysolfkey::~mysolfkey()
{
delete ui;
}
【4.9】mysolfkey.ui
界面设计-
?imageUrl=https%3A%2F%2Fimg-blog.csdnimg.cn%2F87b69ddc437e4c7c8ea1a73ff9335419.png%3Fx-oss-process%3Dimage%2Fwatermark%2Ctype_d3F5LXplbmhlaQ%2Cshadow_50%2Ctext_Q1NETiBA57qi5a6i55m95bi9%2Csize_20%2Ccolor_FFFFFF%2Ct_70%2Cg_se%2Cx_16&valid=false)
【5】事件流程重写了事件处理函数
【5.1】main.cpp
include "mainwindow.h"
include
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
【5.2】mainwindow.cpp
include "mainwindow.h"
include "ui_mainwindow.h"
include
- MainWindow::MainWindow(QWidget *parent)
- QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::mouseDoubleClickEvent(QMouseEvent *event)
{
//打印你双击的坐标位置
qDebug()<<"你双击的是: "<
//判断你用的是哪个键
if(event->button()Qt::LeftButton) //鼠标左键
qDebug()<<"左键双击";
else if(event->button()Qt::RightButton) //鼠标右键
qDebug()<<"右键双击";
else
qDebug()<<"中间键双击";
}
void MainWindow::keyPressEvent(QKeyEvent *event)
{
qDebug()<<"你按下去的是 "<
}
【5.3】mainwindow.h
ifndef MAINWINDOW_H
define MAINWINDOW_H
include
include
include
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
//重写父类的鼠标双击事件的处理函数
void mouseDoubleClickEvent(QMouseEvent *event);
//重写父类的按键事件处理函数
void keyPressEvent(QKeyEvent *event);
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
【5.4】mainwindow.ui
界面设计-
?imageUrl=https%3A%2F%2Fimg-blog.csdnimg.cn%2F5a53f185dc70444faf5c9f9af29690a7.png%3Fx-oss-process%3Dimage%2Fwatermark%2Ctype_d3F5LXplbmhlaQ%2Cshadow_50%2Ctext_Q1NETiBA57qi5a6i55m95bi9%2Csize_20%2Ccolor_FFFFFF%2Ct_70%2Cg_se%2Cx_16&valid=false)
【6】所有源码分享
-
?imageUrl=https%3A%2F%2Fimg-blog.csdnimg.cn%2F4a95a22f66fe43c3b4fe86406fc9326f.png%23pic_center&valid=false)
第八章 往期内容回顾
第六期 mplayer视频播放器+列表框+交叉编译QT程序+QT控制硬件+多进程

浙公网安备 33010602011771号