是否可以从 PyQt5 中的线程获取数组?

Posted

技术标签:

【中文标题】是否可以从 PyQt5 中的线程获取数组?【英文标题】:Is it possible to get an array from a thread in PyQt5? 【发布时间】:2019-06-28 17:31:36 【问题描述】:

我创建了一个代码,该代码从示波器获取信号并在 GUI 内的 pyqtGraph 中实时绘图,但它是锁定的。我正在尝试使用Qthread解锁GUI,但我是一个业余程序员,我不知道这是否正确。

因此,我在不使用示波器的情况下继续尝试使用此代码,并尝试在线程中进行计算并保持 GUI 运行,但我被卡住了。有没有办法在不锁定 GUI 的情况下获取数组 self.s 并制作实时绘图?

import pyqtgraph as pg
import numpy as np
import time
import sys
from PyQt5 import QtGui
from PyQt5.QtWidgets import *
from PyQt5.QtCore import QThread, pyqtSignal


class plotarT(QThread):
    signal = pyqtSignal('PyQt_PyObject')

    def __init__(self):
        QThread.__init__(self)

    def __del__(self):
        self.wait()

    def update(self):
        self.phase = 0
        self.t = np.arange(0, 3.0, 0.01)
        self.s = np.sin(2 * np.pi * self.t + self.phase) #Sin function
        self.phase += 0.1
        time.sleep(2) #To simulate the time that oscilloscope take to respond


    def run(self):
        self.update()
        self.signal.emit('QObject')


class Window(QDialog):
    def __init__(self):
        self.app = QtGui.QApplication(sys.argv)
       super().__init__()
        self.title = "PyQt5 GridLayout"
        self.top = 100
        self.left = 100
        self.width = 1000
        self.height = 600
        self.InitWindow()
        self.traces = dict()
        pg.setConfigOptions(antialias=True)

    def InitWindow(self):
        self.setWindowIcon(QtGui.QIcon("icon.png"))
        self.setWindowTitle(self.title)
        self.setGeometry(self.top, self.left, self.width, self.height)

        self.gridLayoutCreation()
        vboxLayout = QVBoxLayout()
        vboxLayout.addWidget(self.groupBox)
        self.setLayout(vboxLayout)

        self.show()

    def gridLayoutCreation(self): 
        self.groupBox = QGroupBox("Grid Layout Example")

        gridLayout = QGridLayout()
        self.guiplot = pg.PlotWidget()
        gridLayout.addWidget(self.guiplot,0,8,8,12)
        self.groupBox.setLayout(gridLayout)

        gridLayout.addWidget(QLabel('Tempo'), 0,0)
        self.time = QLineEdit('')
        gridLayout.addWidget(self.time, 1,0)


    def plotar(self):
        self.guiplot.clear()
        self.guiplot.plot(s)
        #self.guiplot.plot(c)

    def teste(self):
        self.get_thread = plotarT()
        self.get_thread.start()



def main():
    app = QtGui.QApplication(sys.argv)
    form = Window()
    form.show()
    form.teste()
    app.exec_()

if __name__ == '__main__':
    main()

【问题讨论】:

signal = pyqtSignal(object) ... self.signal.emit(self.s) 【参考方案1】:

试试看:

import pyqtgraph as pg
import numpy as np
#import time
import sys
from PyQt5 import QtGui
from PyQt5.QtWidgets import *
from PyQt5.QtCore import QThread, pyqtSignal


class plotarT(QThread):

    signal = pyqtSignal(object)                             # object

    def __init__(self, parent=None):
        super().__init__()
        self.s  = None                                      # +++
        self.phase = 0                                      # +++

    def __del__(self):
        self.wait()

    def update(self):
#        self.phase = 0                                     # --- 
        self.t = np.arange(0, 3.0, 0.01)
        self.s = np.sin(2 * np.pi * self.t + self.phase)    # Sin function
        self.phase += 0.1
        QThread.msleep(200)    # time.sleep(0.2) 


    def run(self):
        for i in range(100):                                # +++ Some cycle
            self.update()
            self.signal.emit(self.s)                        # self.s


class Window(QDialog):
    def __init__(self):
#        self.app = QtGui.QApplication(sys.argv)
        super().__init__()
        self.title = "PyQt5 GridLayout"
        self.top = 100
        self.left = 100
        self.width = 1000
        self.height = 600
        self.InitWindow()

        self.traces = dict()
        pg.setConfigOptions(antialias=True)

    def InitWindow(self):
        self.setWindowIcon(QtGui.QIcon("icon.png"))
        self.setWindowTitle(self.title)
        self.setGeometry(self.top, self.left, self.width, self.height)

        self.gridLayoutCreation()

        vboxLayout = QVBoxLayout()
        vboxLayout.addWidget(self.groupBox)
        self.setLayout(vboxLayout)

        self.show()

    def gridLayoutCreation(self): 
        self.groupBox = QGroupBox("Grid Layout Example")

        gridLayout   = QGridLayout()
        self.guiplot = pg.PlotWidget()
        gridLayout.addWidget(self.guiplot,0,8,8,12)
        self.groupBox.setLayout(gridLayout)

        gridLayout.addWidget(QLabel('Tempo'), 0,0)
        self.timeEdit = QLineEdit('')                       # time <-> timeEdit
        gridLayout.addWidget(self.timeEdit, 1,0)            # time <-> timeEdit


    def plotar(self, s):                                    
        self.guiplot.clear()
        self.guiplot.plot(s)
        #self.guiplot.plot(c)

    def teste(self):
        self.get_thread = plotarT()
        self.get_thread.signal.connect(self.displayS)        # <--- +++
        self.get_thread.start()

    def displayS(self, self_s):                              # <--- +++
        """ Here is your `self.s` array. 
            Draw a graph in real time without blocking the graphical interface.
        """
#        print("\n Here is your `self.s` array. \n", self_s)

        self.plotar(self_s)


def main():
    app = QApplication(sys.argv)  # QtGui.
    form = Window()
    form.show()
    form.teste()
    app.exec_()

if __name__ == '__main__':
    main()

【讨论】:

以上是关于是否可以从 PyQt5 中的线程获取数组?的主要内容,如果未能解决你的问题,请参考以下文章

迭代器在spark中的应用

java从list中取数,取前三行

python怎么从一堆数据中取数

java中怎样在一个集合中随机取一个数?

PyQt5 中的前后端分离与 QML

从 python 中的 PYQT5 QListview 获取选定文件的文件名