首页 > 解决方案 > 从 ComboBox 实现“选择端口”功能

问题描述

我想要一个程序,从 Arduino 发送和接收数据,我用 PyQt5 制作了一个 GUI,但我有一个问题。我有两个组合框,一个用于选择端口,另一个用于选择波特率,我已经实现了一个选择波特率的功能,但我不知道如何将端口名称从我的第一个组合框发送到功能“defineSerial”可以帮助我吗?

from PyQt5 import QtCore, QtWidgets, QtSerialPort
from PyQt5.uic import loadUi

class Widget(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super(Widget, self).__init__(parent)
        loadUi('/Users/bogdanvesa/P2A_GUI/mainwindow.ui', self)

        self.lcd_StartBtn.clicked.connect(self.send)
        self.connect_btn.clicked.connect(self.connectToPort)
        self.disconnect_btn.clicked.connect(self.disconnectFromPort)
        self.baudrate_comboBox.addItem("1200")
        self.baudrate_comboBox.addItem("2400")
        self.baudrate_comboBox.addItem("4800")
        self.baudrate_comboBox.addItem("9600")
        self.baudrate_comboBox.currentTextChanged.connect(self.defineSerial)

    def defineSerial(self, text):

        if text == '1200':
            self.baudrate = QtSerialPort.QSerialPort.Baud1200
        elif text == '2400':
            self.baudrate = QtSerialPort.QSerialPort.Baud2400
        elif text == '4800':
            self.baudrate = QtSerialPort.QSerialPort.Baud4800
        elif text == '9600':
            self.baudrate = QtSerialPort.QSerialPort.Baud9600
        else:
            print("Invalid")

        self.serial = QtSerialPort.QSerialPort\
                (
            '/dev/tty.usbmodem14201',
            baudRate= self.baudrate,
            readyRead=self.receive
                )

    @QtCore.pyqtSlot()
    def receive(self):
        while self.serial.canReadLine():
            text = self.serial.readLine().data().decode()
            text = text.rstrip('\r\n')
            self.light_lineEdit.setText(text)
            print(text)

    @QtCore.pyqtSlot()
    def send(self):
        self.serial.write(self.lcd_lineEdit.text().encode())

    @QtCore.pyqtSlot()
    def connectToPort(self):
        self.serial.open(QtCore.QIODevice.ReadWrite)

    @QtCore.pyqtSlot(bool)
    def disconnectFromPort(self):
        self.serial.close()

if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)
    w = Widget()
    w.show()
    sys.exit(app.exec_())

标签: pythonserial-portpyqt5

解决方案


最好配置一个 QDialog,这样当您打开该对话框时,可用端口将被刷新:

from PyQt5 import QtCore, QtWidgets, QtSerialPort


class Dialog(QtWidgets.QDialog):
    def __init__(self, parent=None):
        super(Dialog, self).__init__(parent)
        self.portname_comboBox = QtWidgets.QComboBox()
        self.baudrate_comboBox = QtWidgets.QComboBox()

        for info in QtSerialPort.QSerialPortInfo.availablePorts():
            self.portname_comboBox.addItem(info.portName())

        for baudrate in QtSerialPort.QSerialPortInfo.standardBaudRates():
            self.baudrate_comboBox.addItem(str(baudrate), baudrate)

        buttonBox = QtWidgets.QDialogButtonBox()
        buttonBox.setOrientation(QtCore.Qt.Horizontal)
        buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok)
        buttonBox.accepted.connect(self.accept)
        buttonBox.rejected.connect(self.reject)

        lay = QtWidgets.QFormLayout(self)
        lay.addRow("Port Name:", self.portname_comboBox)
        lay.addRow("BaudRate:", self.baudrate_comboBox)
        lay.addRow(buttonBox)
        self.setFixedSize(self.sizeHint())

    def get_results(self):
        return self.portname_comboBox.currentText(), self.baudrate_comboBox.currentData()

class MainWindow(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.lcd_StartBtn = QtWidgets.QPushButton(
            "Send",
            clicked=self.send
        )
        self.lcd_lineEdit = QtWidgets.QLineEdit()
        self.light_lineEdit = QtWidgets.QLineEdit(readOnly=True)

        self.connect_btn = QtWidgets.QPushButton(
            "Connect",
            clicked=self.connectToPort
        )
        self.disconnect_btn = QtWidgets.QPushButton(
            "Disconnect",
            clicked=self.disconnectFromPort
        )
        self.configure_btn = QtWidgets.QPushButton(
            "Configure",
            clicked=self.open_dialog
        )
        central_widget = QtWidgets.QWidget()
        self.setCentralWidget(central_widget)
        lay = QtWidgets.QFormLayout(central_widget)
        lay.addRow(self.connect_btn)
        lay.addRow(self.disconnect_btn)
        hlay = QtWidgets.QHBoxLayout()
        hlay.addWidget(self.lcd_lineEdit)
        hlay.addWidget(self.lcd_StartBtn)
        lay.addRow(hlay)
        lay.addWidget(self.light_lineEdit)
        lay.addRow(self.configure_btn)

        self.serial = QtSerialPort.QSerialPort(
            self,
            readyRead=self.receive
        )

    @QtCore.pyqtSlot()
    def open_dialog(self):
        dialog = Dialog()
        if dialog.exec_():
            portname, baudrate = dialog.get_results()
            self.serial.setPortName(portname)
            self.serial.setBaudRate(baudrate)

    @QtCore.pyqtSlot()
    def receive(self):
        while self.serial.canReadLine():
            text = self.serial.readLine().data().decode()
            text = text.rstrip('\r\n')
            self.light_lineEdit.setText(text)
            print(text)

    @QtCore.pyqtSlot()
    def send(self):
        self.serial.write(self.lcd_lineEdit.text().encode())

    @QtCore.pyqtSlot()
    def connectToPort(self):
        self.serial.open(QtCore.QIODevice.ReadWrite)

    @QtCore.pyqtSlot(bool)
    def disconnectFromPort(self):
        self.serial.close()

if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)
    w = MainWindow()
    w.show()
    sys.exit(app.exec_())

如果您仍想继续使用您的逻辑,那么最大的问题是:您何时需要端口名和波特率?连接中需要这两个参数。

from PyQt5 import QtCore, QtWidgets, QtSerialPort, uic
class Widget(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super(Widget, self).__init__(parent)
        uic.loadUi('/Users/bogdanvesa/P2A_GUI/mainwindow.ui', self)

        self.lcd_StartBtn.clicked.connect(self.send)
        self.connect_btn.clicked.connect(self.connectToPort)
        self.disconnect_btn.clicked.connect(self.disconnectFromPort)
        self.baudrate_comboBox.addItem("1200", QtSerialPort.QSerialPort.Baud1200)
        self.baudrate_comboBox.addItem("2400", QtSerialPort.QSerialPort.Baud2400)
        self.baudrate_comboBox.addItem("4800", QtSerialPort.QSerialPort.Baud4800)
        self.baudrate_comboBox.addItem("9600", QtSerialPort.QSerialPort.Baud9600)

        self.serial = QtSerialPort.QSerialPort(
            self,
            readyRead=self.receive
        )

    @QtCore.pyqtSlot()
    def receive(self):
        while self.serial.canReadLine():
            text = self.serial.readLine().data().decode()
            text = text.rstrip('\r\n')
            self.light_lineEdit.setText(text)
            print(text)

    @QtCore.pyqtSlot()
    def send(self):
        self.serial.write(self.lcd_lineEdit.text().encode())

    @QtCore.pyqtSlot()
    def connectToPort(self):
        self.serial.setPortName(self.portname_comboBox.currentText()) # <---
        self.serial.setBaudRate(self.baudrate_comboBox.currentData()) # <---
        self.serial.open(QtCore.QIODevice.ReadWrite)

    @QtCore.pyqtSlot(bool)
    def disconnectFromPort(self):
        self.serial.close()

if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)
    w = Widget()
    w.show()
    sys.exit(app.exec_())

推荐阅读