1. 说明
本篇文章的***主要功能:***使用QML搭建客户端,使用Python搭建服务端,利用TCP/IP通信方式建立客户端和服务端之间的连接。***作用:***某些情况下,虽然使用QT做了软件开发,但是在工业领域的机器人控制当中有可能需要Python脚本区执行自动化功能,所以需要建立两者之间的通信,达软件界面间接控制机器人的效果。
效果展示:
Qml_Tcp_Python
2. 相关代码如下:
客户端Qt代码
main.qml:
import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Controls 2.2
import QtQuick.Layouts 1.0
Window {
id: window
visible: true
width: 300
height: 300
title: qsTr("Hello World")
Connections{
target: tcpPython
onMessagerecived:{ //响应TcpForPython.cpp中的信号,注意和TCP通信区分开
element2.text = mStr
}
}
Button {
id: button
x: 171
y: 46
text: qsTr("Connect")
onClicked: {
//点击请求TCP连接
tcpPython.newConnect(textInput.text,textInput1.text)
}
}
Rectangle{
id:btline
anchors.left: textInput.left
anchors.right: textInput.right
anchors.top: textInput.bottom
height: 1
color: "black"
}
Rectangle{
id:btline2
x: -23
y: -41
anchors.left: textInput1.left
anchors.right: textInput1.right
anchors.top: textInput1.bottom
height: 1
color: "black"
}
Rectangle{
id:btline3
anchors.left: textInput2.left
anchors.right: textInput2.right
anchors.top: textInput2.bottom
height: 1
color: "black"
}
Text {
id: element
x: 15
y: 42
text: qsTr("IP:")
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
Layout.preferredHeight: 16
Layout.preferredWidth: 21
font.pixelSize: 12
}
TextInput {
id: textInput
x: 41
y: 40
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
width: 80
height: 20
font.pixelSize: 12
}
Text {
id: element1
x: 15
y: 68
text: qsTr("Port:")
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
font.pixelSize: 12
}
TextInput {
id: textInput1
x: 47
y: 65
width: 80
height: 20
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
font.pixelSize: 12
}
Text {
id: element2
x: 36
y: 126
width: 242
height: 64
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
font.pixelSize: 12
}
TextInput {
id: textInput2
x: 29
y: 263
width: 135
height: 20
font.pixelSize: 12
selectByMouse: true
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
}
Button {
id: button1
x: 171
y: 253
text: qsTr("Send")
onClicked: {
//点击发送数据到服务器端
tcpPython.sendMsg(textInput2.text)
}
}
}
TcpForPython.h
#ifndef TCPFORPYTHON_H
#define TCPFORPYTHON_H
#include <QObject>
#include <QTcpSocket>
class TcpForPython : public QObject
{
Q_OBJECT
public:
explicit TcpForPython(QObject *parent = nullptr);
~ TcpForPython();
Q_INVOKABLE void newConnect(QString mIp,QString mPort); //请求连接(QML调用)
Q_INVOKABLE void sendMsg(QByteArray mStr); //发送数据(QML调用)
signals:
void messagerecived(QString mStr); //接收到信息,发送信号告知QML
private:
QTcpSocket *tcpSocket;
QString messageRead; //读数据
QByteArray messageWrite; //发数据
private slots:
void readMessage(); //接收数据
};
#endif // TCPFORPYTHON_H
TcpForPython.cpp
#include "tcpforpython.h"
TcpForPython::TcpForPython(QObject *parent) : QObject(parent)
{
tcpSocket = new QTcpSocket(this);
//建立连接后,检测到有数据发送过来时,调用读取函数
connect(tcpSocket,SIGNAL(readyRead()),this,SLOT(readMessage()));
}
TcpForPython::~TcpForPython()
{
tcpSocket->close();
}
void TcpForPython::newConnect(QString mIp, QString mPort)
{
tcpSocket->abort(); //取消已有的连接
tcpSocket->connectToHost(mIp,mPort.toInt()); //请求连接
}
void TcpForPython::sendMsg(QByteArray mStr)
{
messageWrite = mStr;
tcpSocket->write(messageWrite); //发送数据
}
void TcpForPython::readMessage()
{
//读取1024个字节大小
messageRead = tcpSocket->read(1024);
emit messagerecived(messageRead); //接收到信息,发送信号告知QML
}
注意需要将上面的自定义C++类注册到QML的上下文背景中…
服务端Python代码
import socket
# 创建 socket 对象
serversocket = socket.socket(
socket.AF_INET, socket.SOCK_STREAM)
# 获取本地主机名
host = '127.0.0.1' # 注意:如果上面的客户端是在Windows系统中运行的,则这里的 host = '192.168.244.140',总之host必须要和服务端所在主机相对应,否则连接失败
port = 8888
# 绑定端口号
serversocket.bind((host, port))
# 设置最大连接数,超过后排队
serversocket.listen(1)
if __name__ == "__main__":
# 建立客户端连接
clientsocket, addr = serversocket.accept() # 接受连接,并获取socket和连接地址(ip,port)
print("连接地址: %s" % str(addr))
# 发送数据
msg = 'hello! this is python,ha ha ha....'
clientsocket.send(msg.encode('utf-8'))
while True:
# 循环接受数据
msg = clientsocket.recv(1024)
print(msg.decode('utf-8'))
# 关闭连接
if msg.decode("utf-8") == "4":
print("连接关闭...")
clientsocket.close()