我编写了一个程序,用于从串行发送和接收数据,但是我有一个问题,我想创建一个函数“ connect()”或一个类,并且当我按下按钮时,该函数就会执行,但是如果我在“ MainWindow”类中创建此函数,则“ TestThread”类中的变量“ ser”未初始化,您能帮我吗?
import sys
import serial
from PyQt5.QtWidgets import QMainWindow, QApplication
from PyQt5.QtCore import QThread, pyqtSignal
from PyQt5.uic import loadUi
ser = serial.Serial('/dev/tty.usbmodem14201', 9600, timeout=1)
class TestThread(QThread):
serialUpdate = pyqtSignal(str)
def run(self):
while ser.is_open:
QThread.sleep(1)
value = ser.readline().decode('ascii')
self.serialUpdate.emit(value)
ser.flush()
class MainWindow(QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
loadUi('/Users/bogdanvesa/P2A_GUI/mainwindow.ui', self)
self.thread = TestThread(self)
self.thread.serialUpdate.connect(self.handleSerialUpdate)
self.connect_btn.clicked.connect(self.connectSer)
self.lcd_EBtn.clicked.connect(self.startThread)
def startThread(self):
self.thread.start()
def handleSerialUpdate(self, value):
print(value)
self.lcd_lineEdit.setText(value)
def main():
app = QApplication(sys.argv)
form = MainWindow()
form.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
答案 0 :(得分:1)
我使用了上面重新设计的代码,所以它有一个 mainwindow
,一个 menubar
和一个 statusbar
。我还添加了 QSerialPortInfo 类。此版本将查找活动端口并将其显示在状态栏上。
我只在 rpi 4 和 Windows 10 上测试过。
import sys
from PyQt5 import QtCore, QtWidgets, QtSerialPort
from PyQt5.QtWidgets import QApplication, QMainWindow ,QWidget ,QToolBar ,QHBoxLayout, QAction ,QStatusBar ,QLineEdit ,QPushButton ,QTextEdit , QVBoxLayout
from PyQt5.QtCore import Qt , pyqtSignal
from PyQt5.QtSerialPort import QSerialPortInfo
class AddComport(QMainWindow):
porttnavn = pyqtSignal(str)
def __init__(self, parent , menu):
super().__init__(parent)
menuComporte = menu.addMenu("Comporte")
info_list = QSerialPortInfo()
serial_list = info_list.availablePorts()
serial_ports = [port.portName() for port in serial_list]
if(len(serial_ports)> 0):
antalporte = len(serial_ports)
antal = 0
while antal < antalporte:
button_action = QAction(serial_ports[antal], self)
txt = serial_ports[antal]
portinfo = QSerialPortInfo(txt)
buttoninfotxt = " Ingen informationer"
if portinfo.hasProductIdentifier():
buttoninfotxt = ("Produkt specifikation = " + str(portinfo.vendorIdentifier()))
if portinfo.hasVendorIdentifier():
buttoninfotxt = buttoninfotxt + (" Fremstillers id = "+ str(portinfo.productIdentifier()))
button_action = QAction( txt , self)
button_action.setStatusTip( buttoninfotxt)
button_action.triggered.connect(lambda checked, txt = txt: self.valgAfComportClick(txt))
menuComporte.addAction(button_action)
antal = antal +1
else:
Print("Ingen com porte fundet")
def valgAfComportClick(self , port):
self.porttnavn.emit(port)
def closeEvent(self, event):
selv.close()
class MainWindow(QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
portname = "None"
self.setStatusBar(QStatusBar(self))
menu = self.menuBar()
comfinder = AddComport(self , menu)
comfinder.porttnavn.connect(self.valgAfComport)
self.setWindowTitle("Serial port display / send")
self.message_le = QLineEdit()
self.send_btn = QPushButton(
text="Send",
clicked=self.send
)
self.output_te = QTextEdit(readOnly=True)
self.button = QPushButton(
text="Connect",
checkable=True,
toggled=self.on_toggled
)
lay = QVBoxLayout(self)
hlay = QHBoxLayout()
hlay.addWidget(self.message_le)
hlay.addWidget(self.send_btn)
lay.addLayout(hlay)
lay.addWidget(self.output_te)
lay.addWidget(self.button)
widget = QWidget()
widget.setLayout(lay)
self.setCentralWidget(widget)
self.serial = QtSerialPort.QSerialPort(
portname,
baudRate=QtSerialPort.QSerialPort.Baud9600,
readyRead=self.receive)
@QtCore.pyqtSlot()
def receive(self):
while self.serial.canReadLine():
text = self.serial.readLine().data().decode()
text = text.rstrip('\r\n')
self.output_te.append(text)
@QtCore.pyqtSlot()
def send(self):
self.serial.write(self.message_le.text().encode())
@QtCore.pyqtSlot(bool)
def on_toggled(self, checked):
self.button.setText("Disconnect" if checked else "Connect")
if checked:
if not self.serial.isOpen():
self.serial.open(QtCore.QIODevice.ReadWrite)
if not self.serial.isOpen():
self.button.setChecked(False)
else:
self.button.setChecked(False)
else:
self.serial.close()
def valgAfComport(self , nyport):
seropen = False
if self.serial.isOpen():
seropen = True
self.serial.close()
self.serial.setPortName(nyport)
if seropen:
self.serial.open(QtCore.QIODevice.ReadWrite)
if not self.serial.isOpen():
self.button.setChecked(False)
print(nyport)
def closeEvent(self, event):
self.serial.close()
print("Comport lukket")
print(comporttxt)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
答案 1 :(得分:0)
与其使用pySerial +线程,不如使用Qt事件循环中的QSerialPort
:
from PyQt5 import QtCore, QtWidgets, QtSerialPort
class Widget(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Widget, self).__init__(parent)
self.message_le = QtWidgets.QLineEdit()
self.send_btn = QtWidgets.QPushButton(
text="Send",
clicked=self.send
)
self.output_te = QtWidgets.QTextEdit(readOnly=True)
self.button = QtWidgets.QPushButton(
text="Connect",
checkable=True,
toggled=self.on_toggled
)
lay = QtWidgets.QVBoxLayout(self)
hlay = QtWidgets.QHBoxLayout()
hlay.addWidget(self.message_le)
hlay.addWidget(self.send_btn)
lay.addLayout(hlay)
lay.addWidget(self.output_te)
lay.addWidget(self.button)
self.serial = QtSerialPort.QSerialPort(
'/dev/tty.usbmodem14201',
baudRate=QtSerialPort.QSerialPort.Baud9600,
readyRead=self.receive
)
@QtCore.pyqtSlot()
def receive(self):
while self.serial.canReadLine():
text = self.serial.readLine().data().decode()
text = text.rstrip('\r\n')
self.output_te.append(text)
@QtCore.pyqtSlot()
def send(self):
self.serial.write(self.message_le.text().encode())
@QtCore.pyqtSlot(bool)
def on_toggled(self, checked):
self.button.setText("Disconnect" if checked else "Connect")
if checked:
if not self.serial.isOpen():
if not self.serial.open(QtCore.QIODevice.ReadWrite):
self.button.setChecked(False)
else:
self.serial.close()
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
w = Widget()
w.show()
sys.exit(app.exec_())