【问题标题】:how to insert data from one function into multiple widgets in PyQt5如何将数据从一个函数插入到 PyQt5 中的多个小部件中
【发布时间】:2020-03-09 08:15:34
【问题描述】:

我有一个连接到我的界面的设备,并且想将数据插入到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_())

【问题讨论】:

  • time.sleep 有什么特别的原因吗,或者他们是为了模仿等待?
  • time.sleep 是为了确保从设备中获取所有数据
  • @HoboCoder 更好地解释你的意思,你的问题令人困惑。
  • @eyllanesc 希望编辑能减少混乱
  • @HoboCoder 好的,我更了解你。我仍然有以下疑问:1)如果您删除 time.sleep() 您的代码仍然有效吗? 2) 你必须添加多少个 QLineEdits 来添加文本?他们只有 2 个 QLineEdits 吗?假设信息被发射了两次,所以 2 个 QLineEdits 已经被填充,在下一个发射中应该放置该文本的 QLineEdit?

标签: python pyqt pyqt5 pyserial


【解决方案1】:

您不应在主线程中执行耗时或耗时的循环,因为它们会阻塞事件循环。您必须做的是在辅助线程上执行它并通过信号发送信息。要按顺序获取数据,您可以创建一个迭代器并通过 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_())

【讨论】:

  • 非常感谢@eyllanesc! , 到目前为止尽量避免线程化,我想我需要深入了解它
猜你喜欢
  • 2013-11-08
  • 1970-01-01
  • 2020-08-08
  • 1970-01-01
  • 2020-02-22
  • 2019-05-01
  • 1970-01-01
  • 2021-09-26
相关资源
最近更新 更多