как вставить данные из одной функции в несколько виджетов в PyQt5 - PullRequest
1 голос
/ 09 марта 2020

У меня есть устройство, подключенное к моему интерфейсу, и я хочу вставить данные в QlineEdit виджеты

Эта функция def getdevice_data(self): получает данные с устройства и возвращает их в виде строки

с помощью self.get_output__button.clicked.connect(self.getdevice_data) я «запускаю» функцию

, а с помощью 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_())

1 Ответ

1 голос
/ 09 марта 2020

Вы не должны выполнять трудоемкие или трудоемкие циклы в главном потоке, так как они блокируют событие l oop. Что вы должны сделать, это запустить его во вторичном потоке и отправить информацию через сигналы. Чтобы получить данные последовательно, вы можете создать итератор и получить доступ к каждому элементу через функцию 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_())
...