如何将数据从一个函数插入到 PyQt5 中的多个小部件

how to insert data from one function into multiple widgets in PyQt5

我有一个设备与我的界面相连,想将数据插入 QlineEdit 个小部件

此函数 def getdevice_data(self): 从设备接收数据并 returns 将其作为字符串

self.get_output__button.clicked.connect(self.getdevice_data)我"start"函数

并使用 self.custom_attribute.connect(self.device_input1.setText) 我将输出发送到 QLineEdit 小部件

如何保留函数 运行 并将函数中的新数据插入空行编辑小部件,而不添加多个按钮来一次又一次地启动该函数?

完整代码

import sys
from PyQt5 import QtWidgets as qtw
from PyQt5 import QtCore as qtc
from PyQt5 import QtGui as qtg

import serial
import time


class CustmClass(qtw.QWidget):
    '''
    description einfügen
    '''

    # Attribut Signal
    custom_attribute = qtc.pyqtSignal(str)

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # your code will go here


        # Interface
        self.resize(300, 210)
        # button
        self.get_output__button = qtw.QPushButton("start function ?")
        # lineEdit
        self.device_input1 = qtw.QLineEdit()
        self.device_input2 = qtw.QLineEdit()
        # Layout
        vboxlaout = qtw.QVBoxLayout()
        vboxlaout.addWidget(self.get_output__button)
        vboxlaout.addWidget(self.device_input1)
        vboxlaout.addWidget(self.device_input2)

        self.setLayout(vboxlaout)


        self.show()

        # Funktionalität

        self.get_output__button.clicked.connect(self.getdevice_data)

        self.custom_attribute.connect(self.device_input1.setText)
        # self.custom_attribute.connect(self.device_input2.setText)

    def getdevice_data(self):
        try:
            # Serial() opens a serial port
            my_serial = serial.Serial(port='COM6', baudrate=2400, bytesize=7,
                                      parity=serial.PARITY_NONE, timeout=None, stopbits=1)

            if my_serial.is_open:  
                print("port open")
                # log einfügen
                while my_serial.is_open:  

                    data = my_serial.read()  # wait forever till data arives
                    time.sleep(1)  # delay 

                    data_left = my_serial.inWaiting()  
                    data += my_serial.read(data_left)  

                    data = data.decode("utf-8", "strict")

                    if type(data) == str:
                        print(data)
                        return self.custom_attribute.emit(data)
            else:
                print("zu")

        except serial.serialutil.SerialException:
            print("not open")
            # logger hinzufügen


if __name__ == '__main__':
    app = qtw.QApplication(sys.argv)
    w = CustmClass()
    sys.exit(app.exec_())

你不应该在主线程中执行耗时或耗时的循环,因为它们会阻塞事件循环。您必须做的是在辅助线程上执行它并通过信号发送信息。要按顺序获取数据,您可以创建一个迭代器并通过 next() 函数访问每个元素

import sys
import threading
import time

import serial

from PyQt5 import QtWidgets as qtw
from PyQt5 import QtCore as qtc
from PyQt5 import QtGui as qtg


class SerialWorker(qtw.QObject):
    dataChanged = qtw.pyqtSignal(str)

    def start(self):
        threading.Thread(target=self._execute, daemon=True).start()

    def _execute(self):
        try:
            my_serial = serial.Serial(
                port="COM6",
                baudrate=2400,
                bytesize=7,
                parity=serial.PARITY_NONE,
                timeout=None,
                stopbits=1,
            )
            while my_serial.is_open:
                data = my_serial.read()  # wait forever till data arives
                time.sleep(1)  # delay
                data_left = my_serial.inWaiting()
                data += my_serial.read(data_left)
                data = data.decode("utf-8", "strict")
                print(data)
                self.dataChanged.emit(data)
        except serial.serialutil.SerialException:
            print("not open")


class Widget(qtw.QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.resize(300, 210)
        self.get_output__button = qtw.QPushButton("start function ?")
        self.device_input1 = qtw.QLineEdit()
        self.device_input2 = qtw.QLineEdit()
        # Layout
        vboxlaout = qtw.QVBoxLayout(self)
        vboxlaout.addWidget(self.get_output__button)
        vboxlaout.addWidget(self.device_input1)
        vboxlaout.addWidget(self.device_input2)

        self.serial_worker = SerialWorker()

        self.device_iterator = iter([self.device_input1, self.device_input2])

        self.get_output__button.clicked.connect(self.serial_worker.start)
        self.serial_worker.dataChanged.connect(self.on_data_changed)

    @qtw.pyqtSlot(str)
    def on_data_changed(self, data):
        try:
            device = next(self.device_iterator)
            device.setText(data)
        except StopIteration:
            pass


if __name__ == "__main__":
    app = qtw.QApplication(sys.argv)
    w = CustmClass()
    w.show()
    sys.exit(app.exec_())