PYQT 中radiobutton点击创建线程后卡住
logic_code
```python
from PyQt5.QtWidgets import QMainWindow, QApplication
from PyQt5.QtCore import QTimer, QIODevice
from mywindow import Ui_MainWindow # 导入UI界面文件
from PyQt5 import QtCore, QtGui, QtWidgets
import sys
from serial.tools import list_ports
from PyQt5.QtCore import QTimer, QThread, pyqtSignal
from serial.tools import list_ports
from datetime import datetime
import serial
class RefreshSerialPortsThread(QThread):
ports_refreshed = pyqtSignal(list)
def run(self):
while True:
port_list = [p.device for p in list_ports.comports()] # 此处获取串口列表的逻辑需要根据实际情况编写
self.ports_refreshed.emit(port_list)
self.msleep(1000) # 设置适当的延时以控制刷新频率
class SerialThread(QThread):
print(1)
data_received = pyqtSignal(str)
def __init__(self, serial_port, parent=None):
super(SerialThread, self).__init__(parent)
self.serial_port = serial_port
self.running = True # 添加一个标志来指示线程是否应该继续运行
def run(self):
while self.running: # 使用标志来控制循环
try:
if self.serial_port.isOpen(): # 检查串口是否打开
data = self.serial_port.readline().decode().strip()
if data:
self.data_received.emit(data)
else:
print("err")
else:
print("Serial port is closed.") # 输出提示信息
self.running = False # 设置标志以退出循环
except ValueError as e:
print(f"Error converting data to float: {e}")
except Exception as e:
print(f"Exception in SerialThread: {e}")
# def run(self):
# if not self.serial_port.open(QIODevice.ReadOnly):
# print("Error opening serial port.")
# return
#
# while self.serial_port.isOpen():
# print(2)
# if self.serial_port.waitForReadyRead(100):
# data = self.serial_port.readAll().data().decode()
# self.data_received.emit(data)
def stop(self):
self.running = False # 设置标志以退出循环
class COM_MainWindow(QMainWindow, Ui_MainWindow):
def __init__(self):
super(COM_MainWindow, self).__init__()
Ui_MainWindow.setupUi(self, self)
self.serial_open = False
self.serial_port = None
self.serial_thread = None
self.timer = QTimer()
self.baud_rate = 115200
self.data_bits = 8
self.stop_bits = 1
self.timestamps = []
self.data = []
self.pushButton.clicked.connect(self.save_window) # 连接按钮点击信号和槽函数
self.pushButton_2.clicked.connect(self.clear_receive)
self.pushButton_3.clicked.connect(self.send_data)
self.pushButton_4.clicked.connect(self.clear_send)
self.pushButton_5.clicked.connect(self.stop_send)
self.timer.timeout.connect(self.send_data) # 定时器超时触发发送数据
self.radioButton.clicked.connect(self.toggle_serial)
#实现串口的不停检测
self.refresh_thread = RefreshSerialPortsThread()
self.refresh_thread.ports_refreshed.connect(self.update_serial_ports)
self.refresh_thread.start()
def update_serial_ports(self, port_list):
# 更新界面上的串口列表
self.comboBox.clear()
self.comboBox.addItems(port_list)
def save_window(self):
# 保存窗口逻辑代码
pass
def clear_receive(self):
# 清除接收逻辑代码
pass
def send_data(self):
# 发送数据逻辑代码
pass
def clear_send(self):
# 清除发送逻辑代码
pass
def stop_send(self):
# 停止发送逻辑代码
pass
def open_serial(self):
port_name = self.comboBox.currentText()
self.baud_rate = int(self.baud_rate_box.currentText())
data_bits_text = self.data_bit_box.currentText()
self.data_bits = serial.EIGHTBITS if data_bits_text == "8" else serial.SEVENBITS
stop_bits_text = self.stop_bit_box.currentText()
self.stop_bits = serial.STOPBITS_ONE if stop_bits_text == "1" else \
serial.STOPBITS_ONE_POINT_FIVE if stop_bits_text == "1.5" else \
serial.STOPBITS_TWO
try:
print(6)
self.serial_port = serial.Serial(port=port_name, baudrate=self.baud_rate, timeout=0.1)
self.serial_port.bytesize = self.data_bits
self.serial_port.stopbits = self.stop_bits
print(self.serial_port)
self.serial_thread = SerialThread(self.serial_port)
self.serial_thread.data_received.connect(self.handle_data_received)
self.serial_thread.start()
self.timer.start(1000)
print("Thread started successfully.")
#self.timer.start(500)
self.serial_open = True
except serial.SerialException as e:
print(f"Error opening serial port: {e}")
def stop_serial(self):
if self.serial_thread is not None:
self.serial_thread.quit()
print("thead success quit")
self.serial_thread.wait()
if self.serial_port is not None:
self.serial_port.close()
self.timer.stop()
self.serial_open = False
def toggle_serial(self):
print(5)
#print("Button text before setText:", self.radioButton.text())
if self.serial_open:
self.stop_serial()
self.radioButton.setText("串口关闭")
else:
self.open_serial()
self.radioButton.setText("串口开启")
def refresh_serial_ports(self):
port_list = [p.device for p in list_ports.comports()]
print(port_list)
self.comboBox.clear()
self.comboBox.addItems(port_list)
def handle_data_received(self, data):
try:
timestamp = datetime.now().strftime('%H:%M:%S')
value = float(data)
self.timestamps.append(timestamp)
self.data.append(value)
except ValueError as e:
print(f"Error converting data to float: {e}")
if __name__ == "__main__":
QtCore.QCoreApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling)
App = QApplication(sys.argv) # 创建QApplication对象,作为GUI主程序入口
#aw = Ui_MainWindow() # 创建主窗体对象,实例化Ui_MainWindow
w = COM_MainWindow() # 实例化QMainWindow类
#aw.setupUi(w) # 主窗体对象调用setupUi方法,对QMainWindow对象进行设置
w.show() # 显示主窗体
# App.exit()
sys.exit(App.exec_()) # 循环中等待退出程序 当关闭界面时,只会关闭当前的GUI线程,如果有其他线程在运行是不会关闭的,
#os.exit(App.exec_()) #实现关闭界面即退出系统。
layout_code
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'D:\python\Lib\site-packages\qt5_applications\Qt\bin\COMui.ui'
#
# Created by: PyQt5 UI code generator 5.15.9
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt5 import QtCore, QtGui, QtWidgets
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(786, 827)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.com_sel_label = QtWidgets.QLabel(self.centralwidget)
self.com_sel_label.setGeometry(QtCore.QRect(2, 13, 48, 16))
self.com_sel_label.setObjectName("com_sel_label")
self.comboBox = QtWidgets.QComboBox(self.centralwidget)
self.comboBox.setGeometry(QtCore.QRect(70, 12, 67, 19))
self.comboBox.setObjectName("comboBox")
self.com_baud_rate = QtWidgets.QLabel(self.centralwidget)
self.com_baud_rate.setGeometry(QtCore.QRect(2, 62, 36, 16))
self.com_baud_rate.setObjectName("com_baud_rate")
self.stop_bits = QtWidgets.QLabel(self.centralwidget)
self.stop_bits.setGeometry(QtCore.QRect(2, 87, 36, 16))
self.stop_bits.setObjectName("stop_bits")
self.stop_bit_box = QtWidgets.QComboBox(self.centralwidget)
self.stop_bit_box.setGeometry(QtCore.QRect(70, 86, 67, 19))
self.stop_bit_box.setObjectName("stop_bit_box")
self.stop_bit_box.addItem("")
self.stop_bit_box.addItem("")
self.stop_bit_box.addItem("")
self.label_6 = QtWidgets.QLabel(self.centralwidget)
self.label_6.setGeometry(QtCore.QRect(10, 30, 54, 12))
self.label_6.setText("")
self.label_6.setObjectName("label_6")
self.port_status = QtWidgets.QLabel(self.centralwidget)
self.port_status.setGeometry(QtCore.QRect(2, 38, 48, 16))
self.port_status.setObjectName("port_status")
self.radioButton = QtWidgets.QRadioButton(self.centralwidget)
self.radioButton.setGeometry(QtCore.QRect(70, 38, 71, 16))
self.radioButton.setObjectName("radioButton")
self.pushButton = QtWidgets.QPushButton(self.centralwidget)
self.pushButton.setGeometry(QtCore.QRect(70, 160, 67, 19))
self.pushButton.setObjectName("pushButton")
self.pushButton_2 = QtWidgets.QPushButton(self.centralwidget)
self.pushButton_2.setGeometry(QtCore.QRect(70, 185, 67, 19))
self.pushButton_2.setObjectName("pushButton_2")
self.checkBox = QtWidgets.QCheckBox(self.centralwidget)
self.checkBox.setGeometry(QtCore.QRect(2, 260, 83, 16))
self.checkBox.setObjectName("checkBox")
self.checkBox_3 = QtWidgets.QCheckBox(self.centralwidget)
self.checkBox_3.setGeometry(QtCore.QRect(2, 240, 41, 16))
self.checkBox_3.setObjectName("checkBox_3")
self.checkBox_5 = QtWidgets.QCheckBox(self.centralwidget)
self.checkBox_5.setGeometry(QtCore.QRect(2, 210, 59, 16))
self.checkBox_5.setObjectName("checkBox_5")
self.textEdit = QtWidgets.QTextEdit(self.centralwidget)
self.textEdit.setGeometry(QtCore.QRect(140, 0, 641, 301))
self.textEdit.setObjectName("textEdit")
self.pushButton_3 = QtWidgets.QPushButton(self.centralwidget)
self.pushButton_3.setGeometry(QtCore.QRect(70, 230, 67, 19))
self.pushButton_3.setObjectName("pushButton_3")
self.pushButton_4 = QtWidgets.QPushButton(self.centralwidget)
self.pushButton_4.setGeometry(QtCore.QRect(70, 210, 67, 19))
self.pushButton_4.setObjectName("pushButton_4")
self.pushButton_5 = QtWidgets.QPushButton(self.centralwidget)
self.pushButton_5.setGeometry(QtCore.QRect(70, 250, 67, 19))
self.pushButton_5.setObjectName("pushButton_5")
self.checkBox_6 = QtWidgets.QCheckBox(self.centralwidget)
self.checkBox_6.setGeometry(QtCore.QRect(2, 280, 91, 16))
self.checkBox_6.setObjectName("checkBox_6")
self.checkBox_7 = QtWidgets.QCheckBox(self.centralwidget)
self.checkBox_7.setGeometry(QtCore.QRect(2, 300, 71, 16))
self.checkBox_7.setObjectName("checkBox_7")
self.label_8 = QtWidgets.QLabel(self.centralwidget)
self.label_8.setGeometry(QtCore.QRect(20, 320, 24, 16))
self.label_8.setObjectName("label_8")
self.lineEdit = QtWidgets.QLineEdit(self.centralwidget)
self.lineEdit.setGeometry(QtCore.QRect(50, 320, 41, 19))
self.lineEdit.setObjectName("lineEdit")
self.label_9 = QtWidgets.QLabel(self.centralwidget)
self.label_9.setGeometry(QtCore.QRect(100, 320, 16, 16))
self.label_9.setObjectName("label_9")
self.tableWidget = QtWidgets.QTableWidget(self.centralwidget)
self.tableWidget.setGeometry(QtCore.QRect(140, 311, 641, 101))
self.tableWidget.setObjectName("tableWidget")
self.tableWidget.setColumnCount(3)
self.tableWidget.setRowCount(0)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setHorizontalHeaderItem(0, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setHorizontalHeaderItem(1, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setHorizontalHeaderItem(2, item)
self.widget = QtWidgets.QWidget(self.centralwidget)
self.widget.setGeometry(QtCore.QRect(150, 490, 120, 80))
self.widget.setObjectName("widget")
self.data_bits = QtWidgets.QLabel(self.centralwidget)
self.data_bits.setGeometry(QtCore.QRect(2, 112, 36, 16))
self.data_bits.setObjectName("data_bits")
self.data_bit_box = QtWidgets.QComboBox(self.centralwidget)
self.data_bit_box.setGeometry(QtCore.QRect(70, 111, 67, 19))
self.data_bit_box.setObjectName("data_bit_box")
self.data_bit_box.addItem("")
self.data_bit_box.addItem("")
self.data_bit_box.addItem("")
self.data_bit_box.addItem("")
self.verify_bits = QtWidgets.QLabel(self.centralwidget)
self.verify_bits.setGeometry(QtCore.QRect(2, 137, 36, 16))
self.verify_bits.setObjectName("verify_bits")
self.baud_rate_box = QtWidgets.QComboBox(self.centralwidget)
self.baud_rate_box.setGeometry(QtCore.QRect(70, 61, 67, 19))
self.baud_rate_box.setObjectName("baud_rate_box")
self.baud_rate_box.addItem("")
self.baud_rate_box.addItem("")
self.baud_rate_box.addItem("")
self.baud_rate_box.addItem("")
self.baud_rate_box.addItem("")
self.baud_rate_box.addItem("")
self.baud_rate_box.addItem("")
self.baud_rate_box.addItem("")
self.baud_rate_box.addItem("")
self.baud_rate_box.addItem("")
self.baud_rate_box.addItem("")
self.baud_rate_box.addItem("")
self.baud_rate_box.addItem("")
self.baud_rate_box.addItem("")
self.comboBox_5 = QtWidgets.QComboBox(self.centralwidget)
self.comboBox_5.setGeometry(QtCore.QRect(70, 136, 67, 19))
self.comboBox_5.setObjectName("comboBox_5")
self.comboBox_5.addItem("")
self.comboBox_5.addItem("")
self.comboBox_5.addItem("")
self.checkBox_2 = QtWidgets.QCheckBox(self.centralwidget)
self.checkBox_2.setGeometry(QtCore.QRect(2, 190, 41, 16))
self.checkBox_2.setObjectName("checkBox_2")
self.checkBox_4 = QtWidgets.QCheckBox(self.centralwidget)
self.checkBox_4.setGeometry(QtCore.QRect(2, 160, 71, 16))
self.checkBox_4.setObjectName("checkBox_4")
MainWindow.setCentralWidget(self.centralwidget)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "ComWindow"))
self.com_sel_label.setText(_translate("MainWindow", "串口选择"))
self.com_baud_rate.setText(_translate("MainWindow", "波特率"))
self.stop_bits.setText(_translate("MainWindow", "停止位"))
self.stop_bit_box.setItemText(0, _translate("MainWindow", "1"))
self.stop_bit_box.setItemText(1, _translate("MainWindow", "1.5"))
self.stop_bit_box.setItemText(2, _translate("MainWindow", "2"))
self.port_status.setText(_translate("MainWindow", "串口状态"))
self.radioButton.setText(_translate("MainWindow", "串口关闭"))
self.pushButton.setText(_translate("MainWindow", "保存窗口"))
self.pushButton_2.setText(_translate("MainWindow", "清除接收"))
self.checkBox.setText(_translate("MainWindow", "hex显示"))
self.checkBox_3.setText(_translate("MainWindow", "RTS"))
self.checkBox_5.setText(_translate("MainWindow", "时间戳"))
self.pushButton_3.setText(_translate("MainWindow", "发送"))
self.pushButton_4.setText(_translate("MainWindow", "清除发送"))
self.pushButton_5.setText(_translate("MainWindow", "停止发送"))
self.checkBox_6.setText(_translate("MainWindow", "hex发送"))
self.checkBox_7.setText(_translate("MainWindow", "定时发送"))
self.label_8.setText(_translate("MainWindow", "周期"))
self.label_9.setText(_translate("MainWindow", "ms"))
item = self.tableWidget.horizontalHeaderItem(0)
item.setText(_translate("MainWindow", "单条发送"))
item = self.tableWidget.horizontalHeaderItem(1)
item.setText(_translate("MainWindow", "多条发送"))
item = self.tableWidget.horizontalHeaderItem(2)
item.setText(_translate("MainWindow", "帮助"))
self.data_bits.setText(_translate("MainWindow", "数据位"))
self.data_bit_box.setItemText(0, _translate("MainWindow", "8"))
self.data_bit_box.setItemText(1, _translate("MainWindow", "7"))
self.data_bit_box.setItemText(2, _translate("MainWindow", "6"))
self.data_bit_box.setItemText(3, _translate("MainWindow", "5"))
self.verify_bits.setText(_translate("MainWindow", "校验位"))
self.baud_rate_box.setItemText(0, _translate("MainWindow", "19200"))
self.baud_rate_box.setItemText(1, _translate("MainWindow", "38400"))
self.baud_rate_box.setItemText(2, _translate("MainWindow", "43000"))
self.baud_rate_box.setItemText(3, _translate("MainWindow", "57600"))
self.baud_rate_box.setItemText(4, _translate("MainWindow", "76800"))
self.baud_rate_box.setItemText(5, _translate("MainWindow", "115200"))
self.baud_rate_box.setItemText(6, _translate("MainWindow", "128000"))
self.baud_rate_box.setItemText(7, _translate("MainWindow", "230400"))
self.baud_rate_box.setItemText(8, _translate("MainWindow", "256000"))
self.baud_rate_box.setItemText(9, _translate("MainWindow", "460800"))
self.baud_rate_box.setItemText(10, _translate("MainWindow", "921600"))
self.baud_rate_box.setItemText(11, _translate("MainWindow", "1000000"))
self.baud_rate_box.setItemText(12, _translate("MainWindow", "2000000"))
self.baud_rate_box.setItemText(13, _translate("MainWindow", "3000000"))
self.comboBox_5.setItemText(0, _translate("MainWindow", "None"))
self.comboBox_5.setItemText(1, _translate("MainWindow", "Odd"))
self.comboBox_5.setItemText(2, _translate("MainWindow", "Even"))
self.checkBox_2.setText(_translate("MainWindow", "DTR"))
self.checkBox_4.setText(_translate("MainWindow", "自动保存"))
# if __name__ == "__main__":
# QtCore.QCoreApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling)
# App = QApplication(sys.argv) # 创建QApplication对象,作为GUI主程序入口
# aw = Ui_MainWindow() # 创建主窗体对象,实例化Ui_MainWindow
# w = QMainWindow() # 实例化QMainWindow类
# aw.setupUi(w) # 主窗体对象调用setupUi方法,对QMainWindow对象进行设置
# w.show() # 显示主窗体
# # App.exit()
# sys.exit(App.exec_()) # 循环中等待退出程序 当关闭界面时,只会关闭当前的GUI线程,如果有其他线程在运行是不会关闭的,
# #os.exit(App.exec_()) #实现关闭界面即退出系统。
```