1. QML--TCP通讯连接

1. 说明

一般QT/QML用来开发桌面程序或者嵌入式软件,作为上位机开发时,还需要与下位机进行通讯才能实现控制,一般多用于机器人行业当中。实现通讯的方式有很多种,比较常见的包括串口通信和TCP网络通信等,本文将简要介绍TCP通讯方式。
效果展示:

TCP通讯连接

2. 实现步骤

TCP通信需要使用的QT当中的QTcpServerQTcpSocket两个类
第一步:
创建tcpServer类,属于服务端,用于监听客户端的请求连接,详看注释,代码如下:
tcpServer.h:

#ifndef TCPSEVER_H
#define TCPSEVER_H

#include <QObject>
#include <QDebug>
#include <QTcpServer>
#include <QTcpSocket>
#include <QByteArray>

class TcpSever : public QObject
{
    Q_OBJECT
public:
    explicit TcpSever(QObject *parent = nullptr);

    Q_INVOKABLE void startListen();//此函数用于QML端调用,启动监听

signals:
	void sendConnectSuc(QString mStr);
public slots:
    void newConnect();//监听启动后,发现新的连接后,触发这个槽函数

private:
	//服务端既需要tcpServer也需要tcpSocket
    QTcpServer *tcpSever;
    QTcpSocket *tcpSocket;

    QByteArray m_data;
};

#endif // TCPSEVER_H

tcpServer.cpp:

#include "tcpsever.h"

TcpSever::TcpSever(QObject *parent) : QObject(parent)
{

}

void TcpSever::startListen()
{
    tcpSever = new QTcpServer(this);
    tcpSever->listen(QHostAddress::Any,6666);	//启动监听
    //TcpServer端检测到新的连接请求后,会发射newConnection()信号
    connect(tcpSever,SIGNAL(newConnection()),this,SLOT(newConnect()));//绑定信号槽

	emit sendConnectSuc("listening....");
}

void TcpSever::newConnect()
{
    tcpSocket = tcpSever->nextPendingConnection();//当连接成功后,获取客户端套接字,其中包含了一些ip/port信息

    QString ip = tcpSocket->peerAddress().toString();//获取ip地址
    quint16 port = tcpSocket->peerPort();//获取端口号

    QString temp = QString::fromLocal8Bit("[%1:%2]:sucess connected...").arg(ip).arg(port);
    
    emit sendConnectSuc(temp);
}

第二步:
创建tcpSocket类,属于客户端,用于向服务端发送连接请求,详看注释,代码如下:
tcpSocket.h:

#ifndef TCPSOCKET_H
#define TCPSOCKET_H

#include <QObject>
#include <QTcpSocket>
#include <QHostAddress>

class TcpSocket : public QObject
{
    Q_OBJECT
public:
    explicit TcpSocket(QObject *parent = nullptr);

    Q_INVOKABLE void askConnect();//供QML端调用,用于向客户端发送连接请求

signals:
	void sendAskCommand(QString mStr);
private:
	//客户端不需要监听,只需要tcpSocket即可
    QTcpSocket *tcpSocket;

};
#endif // TCPSOCKET_H

tcpSocket.cpp:

#include "Tcpsocket.h"

TcpSocket::TcpSocket(QObject *parent) : QObject(parent)
{
    tcpSocket = new QTcpSocket(this);//创建对象
}

void TcpSocket::askConnect()
{
	//调用connectToHost(ip,port)函数,向服务端请求连接
	//ip,port值是客户端这边决定的
    tcpSocket->connectToHost(QHostAddress("127.0.0.1"),6666);
    
    emit sendAskCommand("asking.....");
}

第三步:
main.cpp文件中,将上面两个类注册到QML的上下文背景中,以方便在QML中进行调用,代码如下:

#include <QQmlContext>
#include "tcpsever.h"
#include "Tcpsocket.h"

TcpSever tcp;
engine.rootContext()->setContextProperty("tcp",&tcp);
TcpSocket tcpsocket;
engine.rootContext()->setContextProperty("tcpSocket",&tcpsocket);

第四步:
main.qml文件中设置两个按钮,调用上面的函数,先启动监听,再进行连接请求。

import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Controls 2.1

Window {
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")

    Connections{
        target: tcp		//响应tcpSever中的信号
        property var i: 1
        onSendConnectSuc:{
            severModel.append({index:i++,str:mStr})
        }
    }
    Connections{
        target: tcpSocket	//响应tcpSocket中的信号
        property var j: 1
        onSendAskCommand:{
            socketModel.append({index:j++,str:mStr})
        }
    }

    Button{
        id:listenBtn	//启动监听按钮
        width: 100
        height: 50
        anchors.left: parent.left
        anchors.top: parent.top
        anchors.topMargin: 10
        anchors.leftMargin: 10
        text:"StartListen"
        onClicked: {
            tcp.startListen();
        }
    }
    Button{
        id:askConnect	//请求连接按钮
        width: 100
        height: 50
        anchors.right: parent.right
        anchors.rightMargin:10
        anchors.top: parent.top
        anchors.topMargin: 10
        text: "AskConnect"
        onClicked: {
            tcpSocket.askConnect()
        }
    }
    ListView{
        id:severView	//显示服务端信息的view视图
        anchors.top: listenBtn.top
        anchors.left: listenBtn.right
        anchors.leftMargin: 5
        anchors.right: parent.horizontalCenter
        height: parent.height
        clip:true
        model:ListModel{
            id:severModel
//            ListElement{
//                index:"1"
//                str:"the first data..."
//            }
        }
        delegate: Rectangle{
            width: parent.width
            height: 10
            Text{
                id:severxuhao
                width: 50
                height: parent.height
                anchors.verticalCenter: parent.verticalCenter
                text: index
            }
            Text{
                id:severcontent
                height: parent.height
                anchors.left: severxuhao.right
                anchors.leftMargin: 5
                anchors.verticalCenter: parent.verticalCenter
                text: str
            }
        }
    }
    ListView{
        id:socketView	//显示客户端信息的view视图
        anchors.top: askConnect.top
        anchors.right: askConnect.left
        anchors.rightMargin: 5
        width: 200
        height: parent.height
        clip:true
        model:ListModel{
            id:socketModel
//            ListElement{
//                index:"1"
//                str:"the first data..."
//            }
        }
        delegate: Rectangle{
            width: parent.width
            height: 10
            Text{
                id:socketxuhao
                width: 7
                height: parent.height
                anchors.right: parent.right
                anchors.verticalCenter: parent.verticalCenter
                text: index
                color: "red"
            }
            Text{
                id:socketcontent
                height: parent.height
                anchors.left: parent.left
                anchors.leftMargin: 5
                anchors.verticalCenter: parent.verticalCenter
                text: str
                color: "red"
            }
        }
    }
}

持续更新中,请大家多多关注…

  • 3
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

山间点烟雨

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值