我想装一个python qt试试,我之前都是用c++ qt
直接上 PySide6
(Qt 官方 Python 绑定,优先选这个,不要 PyQt6)
理由:Qt 官方维护,LGPL 协议宽松,类名、API 和 C++Qt 几乎一模一样,你有 C++Qt 基础,上手几乎零成本
PyQt6 是第三方,商用要付费,直接排除。
最小 Demo
cpp
from PySide6.QtWidgets import QApplication, QMainWindow, QPushButton, QVBoxLayout, QWidget
import sys
# 主窗口类,和C++的class MainWindow : public QMainWindow 完全对应
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("PySide6 测试窗口")
self.resize(400,220)
# 中心部件 + 布局
central_widget = QWidget()
self.setCentralWidget(central_widget)
layout = QVBoxLayout(central_widget)
self.btn = QPushButton("点击按钮")
layout.addWidget(self.btn)
# 信号槽:C++ connect(btn,&QPushButton::clicked,this,&xxx);
self.btn.clicked.connect(self.on_button_click)
def on_button_click(self):
self.btn.setText("按钮被点击了!")
if __name__ == "__main__":
app = QApplication(sys.argv)
win = MainWindow()
win.show()
sys.exit(app.exec())

前置条件:
Windows 安装步骤(推荐先建虚拟环境,隔离包)
打开 Windows Terminal / PowerShell
bash
# 1. 创建虚拟环境(文件夹叫env,只装本次项目依赖)
python -m venv pyside_env
# 2. 激活虚拟环境(Windows)
.\pyside_env\Scripts\activate

激活成功后,命令行前面会出现 (pyside_env)
cpp
# 3. 安装PySide6
pip install pyside6
装好自带工具:pyside6-designer 直接启动 Qt Designer!就是你熟悉的拖拽 UI 编辑器,不用额外装 Qt Creator。
验证安装:
bash
python -c "import PySide6;print(PySide6.__version__)"

为什么需要创建虚拟环境
虚拟环境就是给每个 Python 项目单独 "隔离一套独立的 Python 解释器 + 包",项目之间互不干扰。
你写 C/C++ 习惯了,我用你熟悉的开发场景类比。
类比 C/C++ 项目
C/C++:不同项目依赖不同版本的库,一般靠单独的编译环境、CMake 工具链、vcpkg/conan 的独立包目录隔离;如果所有项目共用一套全局库,版本冲突就会编译报错。
Python 默认(不建虚拟环境):所有项目共用同一个全局 pip 包目录。所有库全部装在一处。
虚拟环境解决的核心问题
解决包版本冲突(最主要目的)
举个例子:
- 项目 A(PySide6 上位机):需要
pyside6==6.7.0 - 项目 B(老脚本):需要
pyside6==6.4.2
如果装在全局:后安装的版本会覆盖前面的版本,其中一个项目直接报错。
虚拟环境:A 的环境装 6.7,B 的环境装 6.4,互相看不见,完全隔离。
你后面可能还会装 rich、textual、numpy、scipy,不同库对依赖版本要求不一样,很容易踩坑。
让ai生成了一个复杂点的程序:
cpp
from PySide6.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout,
QPushButton, QTableWidget, QTableWidgetItem, QLabel, QLineEdit, QHeaderView)
from PySide6.QtCore import QTimer, Qt
from PySide6.QtCharts import QChart, QChartView, QLineSeries, QValueAxis
from PySide6.QtGui import QPen, QPainter # 增加 QPainter
import sys
import random
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("PySide6 UDP报文监控上位机")
self.resize(900, 600)
# 采集状态标记
self.is_running = False
self.data_count = 0
self.series = QLineSeries() # 波形曲线
# 定时器:模拟UDP接收报文,100ms触发一次
self.timer = QTimer()
self.timer.timeout.connect(self.on_timer_recv)
# ========== 中心部件与总布局 ==========
central_widget = QWidget()
self.setCentralWidget(central_widget)
main_layout = QHBoxLayout(central_widget)
# 左侧布局:控制 + 报文表格
left_widget = QWidget()
left_layout = QVBoxLayout(left_widget)
left_widget.setFixedWidth(420)
# 控制行:IP、端口、按钮
ctrl_layout = QHBoxLayout()
ctrl_layout.addWidget(QLabel("目标IP:"))
self.edit_ip = QLineEdit("127.0.0.1")
ctrl_layout.addWidget(self.edit_ip)
ctrl_layout.addWidget(QLabel("端口:"))
self.edit_port = QLineEdit("8888")
ctrl_layout.addWidget(self.edit_port)
left_layout.addLayout(ctrl_layout)
# 功能按钮行
btn_layout = QHBoxLayout()
self.btn_start = QPushButton("开始采集")
self.btn_start.clicked.connect(self.toggle_collect)
self.btn_clear = QPushButton("清空表格")
self.btn_clear.clicked.connect(self.clear_table)
btn_layout.addWidget(self.btn_start)
btn_layout.addWidget(self.btn_clear)
left_layout.addLayout(btn_layout)
# 报文表格
self.table = QTableWidget()
self.table.setColumnCount(3)
self.table.setHorizontalHeaderLabels(["序号", "数值", "时间戳"])
self.table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
left_layout.addWidget(self.table)
# ========== 右侧:QChart波形图 ==========
self.chart = QChart()
self.chart.setTitle("实时信号波形")
self.chart.addSeries(self.series)
# 坐标轴
self.axis_x = QValueAxis()
self.axis_x.setTitleText("采样点")
self.axis_x.setRange(0, 50)
self.axis_y = QValueAxis()
self.axis_y.setTitleText("幅值")
self.axis_y.setRange(0, 100)
self.chart.addAxis(self.axis_x, Qt.AlignBottom)
self.chart.addAxis(self.axis_y, Qt.AlignLeft)
self.series.attachAxis(self.axis_x)
self.series.attachAxis(self.axis_y)
pen = QPen(Qt.blue)
pen.setWidth(2)
self.series.setPen(pen)
chart_view = QChartView(self.chart)
# ========== 修复这一行 ==========
chart_view.setRenderHint(QPainter.RenderHint.Antialiasing)
# 左右布局加入总布局
main_layout.addWidget(left_widget)
main_layout.addWidget(chart_view)
def toggle_collect(self):
"""启停采集"""
if not self.is_running:
self.is_running = True
self.btn_start.setText("停止采集")
self.timer.start(100) # 100ms周期
else:
self.is_running = False
self.btn_start.setText("开始采集")
self.timer.stop()
def on_timer_recv(self):
"""定时器回调:模拟收到UDP报文"""
self.data_count += 1
# 模拟信号值
val = random.randint(20,80)
# 插入表格新行
row = self.table.rowCount()
self.table.insertRow(row)
self.table.setItem(row, 0, QTableWidgetItem(str(self.data_count)))
self.table.setItem(row, 1, QTableWidgetItem(str(val)))
self.table.setItem(row, 2, QTableWidgetItem(f"{self.data_count*0.1:.1f}s"))
# 添加波形点,只保留最近50个点
self.series.append(self.data_count, val)
if self.series.count() > 50:
self.series.remove(0)
def clear_table(self):
"""清空表格与波形"""
self.table.setRowCount(0)
self.series.clear()
self.data_count = 0
if __name__ == "__main__":
app = QApplication(sys.argv)
win = MainWindow()
win.show()
sys.exit(app.exec())

PySide6 示例:UDP 报文监控简易上位机
功能:
- 窗口分面板:参数设置、报文接收表格、实时波形曲线(QChart)
- QTimer 模拟 UDP 接收数据(你后续可以直接替换成真实 socket recv)
- 收到数据自动填入表格,同时绘制波形
- 【开始 / 停止】按钮控制采集
- 清空表格按钮