Python+Qt+OpenGL实时绘制3D轨迹

发布于 2024-08-15  85 次阅读


demo下载路径:https://lingmeng.cc/wp-content/uploads/2024/08/python_3D_Qt_demo.zip

运行效果(先安装必要运行库:同时运行main及send【TCP服务端】):

1.使用Qt设计师制作界面:

2.导出python文件及保存ui文件:

3.编写主程序main.py

import sys
import numpy as np
from ui_untitled import Ui_MainWindow
from PySide2.QtWidgets import QTextBrowser ,QMainWindow ,QGridLayout,QApplication,QDialog
from threading import Thread
from TCP import feedback
from PySide2.QtCore import QObject ,Signal
import time
import pyqtgraph.opengl as gl
import pyqtgraph as pg

class MySignals(QObject):
    # 定义一种信号,两个参数 类型分别是: QTextBrowser 和 字符串
    # 调用 emit方法 发信号时,传入参数 必须是这里指定的 参数类型
    update_table = Signal(QTextBrowser,str)
global_ms = MySignals()

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        # 使用ui文件导入定义界面类
        self.ui = Ui_MainWindow()
        # 初始化界面
        self.ui.setupUi(self)
        global ping_sj
        #连接按钮
        self.ui.connect.clicked.connect(self.connect_tcp)

        global_ms.update_table.connect(self.style_p)
        ################# 初始参数
        self.Link = True
        self.TCP_3Ds = np.array
        self.TCP_3D =[]
        #################3D窗口
        app = pg.mkQApp("GLTextItem Example")
        self.gvw = gl.GLViewWidget()
        self.gvw.show()
        self.gvw.setWindowTitle('pyqtgraph example: GLTextItem')
        griditem = gl.GLGridItem()
        griditem.setSize(100, 100)
        griditem.setSpacing(1, 1)
        griditem.setColor(color=(190, 190, 190))
        self.gvw.addItem(griditem)
        axisitem = gl.GLAxisItem()
        self.gvw.addItem(axisitem)
        self.txtitem2 = gl.GLLinePlotItem()
        self.LineFigureLayout = QGridLayout(self.ui.groupBox3D)
        self.LineFigureLayout.addWidget(self.gvw)
        ##################################
        try:
            self.thread16 = Thread(target=self.plot_3D,
                                   daemon=True  # 设置新线程为daemon线程
                                   )
            self.thread16.start()
        except:
            print('3D错误')

    def style_p(self, fb, text):
        fb.setStyleSheet(text)

    def connect_tcp(self):
        try:
            print("启动连接")
            self.thread6 = Thread(target=self.connects,
                                  daemon=True  # 设置新线程为daemon线程
                                  )
            self.thread6.start()
        except:
            print('链接错误')

    def connects(self):
        self.IP = self.ui.lineEdit.text()
        if self.Link:
            try:
                self.feedback_i = feedback(self.IP, 2233)
                self.ui.connect.setText("断开")
                self.Link = False
                global_ms.update_table.emit(self.ui.lineEdit, (u"background-color: rgb(74, 255, 158);\n"
                                                         "color: rgb(85, 170, 255);\n"
                                                         "border-radius: 5px;"))
            except:
                print("链接失败")
        else:
            try:
                self.Link = True
                self.ui.connect.setText("链接")
                self.feedback_i.close()
                global_ms.update_table.emit(self.ui.lineEdit, (u"background-color: rgb(85, 170, 255);\n"
                                                               "color: rgb(74, 255, 158);\n"
                                                               "border-radius: 5px;"))
            except:
                print("断开链接失败")
        while self.Link ==False:
            try:
                sdc = self.feedback_i.Reply()
                self.TCP_3D.append(sdc)
                if len(self.TCP_3D) > 300:
                    self.TCP_3D.pop(0)
                self.TCP_3Ds = np.array(self.TCP_3D)
            except:
                print("连接出错")

    def plot_3D(self):
        while True :
            if self.Link ==False:
                  try:
                      time.sleep(0.1)  #100ms刷新一次
                      self.txtitem2.setData(pos=(self.TCP_3Ds * 0.01), color=(25, 0, 0, 76.5), width=3,
                                            antialias=True, mode='line_strip')
                      self.gvw.addItem(self.txtitem2)
                  except:
                      time.sleep(0.3)
                      print("3D绘制错误")
            else:
                time.sleep(0.3)


if __name__ == "__main__":
    app = QApplication([])
    mainw = MainWindow()
    mainw.show()
    sys.exit(app.exec_())

4.编写TCP客户端TCP.py

import socket
import numpy as np

class feedback():
    def __init__(self, ip, port):
        self.ip = ip
        self.port = port
        self.socket_feedback = 0
        self.socket_feedback = socket.socket()
        self.socket_feedback.settimeout(1)
        self.socket_feedback.connect((self.ip, self.port))
    def Reply(self):
        data = self.socket_feedback.recv(1024)
        self.feedback_r = bytes.decode(data, 'utf-8')
        lst = self.feedback_r.split(',')
        num_list = [float(x) for x in lst]
        print(num_list)
        return num_list
    def close(self):
            self.socket_feedback.close()

5.编写TCP服务端send.py

import socket
import time
import math
def TCPserver():
    tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    tcp_server_socket.bind(('127.0.0.1', 2233))
    print("等待连接")
    tcp_server_socket.listen(64)
    client_socket = tcp_server_socket.accept()
    client_socket = client_socket[0]
    # recv_data=client_socket.recv(1024)  #每次最多接收1k字节
    # print('接收到:', recv_data.decode('utf-8'))
    return client_socket
client_socket = TCPserver()
print("连接成功")
while True:
    try:
        while True:
            theta = 0
            r = 100
            for i in range(400):
                x = r * theta * math.cos(theta)
                y = r * theta * math.sin(theta)
                z = theta * 50
                theta += 0.1
                client_socket.send(f"{x},{y},{z}".encode('utf-8'))
                time.sleep(0.05)
    except:
        print("发送失败")
        client_socket = TCPserver()
        print("连接成功")

6同时运行服务程序和main.py就实现了3D轨迹嵌入Qt;