我试图从DHT11温度传感器获取一个值,然后通过GUI主窗口小部件绘制它,这个窗口小部件有三个按钮,第一个是开始从传感器获取值,第二个是实时绘制值,第三个是绘制值的FFT。在
问题是我不能将实时图和FFT图分成两个图形,因为每次我将def plotFFTButton_clicked(self):
下的plt.figure(1)
更改为plt.figure(2)
,当我按下FFT绘图按钮时,会出现以下错误:
运行时错误:主线程不在主循环中
另一个问题是我不能删除def runValue(self):
下的plt.figure(1)
,因为它会给我同样的错误。在
如果有人能帮我找到代码的问题,我会很感激的。在
from PyQt4 import QtCore, QtGui
import sys
import time
from threading import Event, Thread
from mainwindow import Ui_MainWindow
from PyQt4.Qt import QString, QFileDialog
from pylab import *
import threading
from threading import Thread
#DH11 tempSensor Library
import Adafruit_DHT
#Library to find FFT and FFTshift
from scipy.fftpack import fft, fftshift
from numpy import linspace
class dataAcquisition(QtGui.QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
super(dataAcquisition, self).__init__(parent)
self.setupUi(self)
self.startButton.clicked.connect(self.startButton_clicked)
self.th = Thread(target = self.runValue)
self.plotRTButton.clicked.connect(self.plotRTButton_clicked)
self.plotFFTButton.clicked.connect(self.plotFFTButton_clicked)
self.Value = 0.0
self.X = 0.0
self.Y = 0.0
self.ChageValueState = False
def runValue(self):
self.X = []
self.Y = []
i = 0.0
plt.figure(1) #an error comes out if I delete this
while True:
self.ChageValueState = True
self.Value = Adafruit_DHT.read_retry(11, 4)[1] #Or you could give the self.Value any number
i += 0.10
self.X.append(i)
self.Y.append(self.Value)
pause(0.01)
def startButton_clicked(self):
self.th.start()
def plotRTButton_clicked(self):
plt.figure(1)
ax1 = subplot(3, 1, 1)
Line1 = plot(0,0,'r-')[0]
Line1.set_xdata(self.X)
Line1.set_ydata(self.Y)
ax1.relim()
ax1.autoscale_view()
def plotFFTButton_clicked(self):
Fs = 8000
N = 256
f = linspace(-Fs/2, Fs/2, N)
plt.figure(1) #an error comes out if I plot in a new figure
ax2 = plt.subplot(3, 1, 2)
Line2 = plot(f,0*f,'r-')[0]
FFT = log10(abs(fft(self.Y, N)))
FFT = fftshift(FFT)
Line2.set_ydata(FFT)
ax2.relim()
ax2.autoscale_view()
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
MainWindow = dataAcquisition()
MainWindow.show()
sys.exit(app.exec_())
该错误是一种安全预防措施,可防止线程中的干扰。每个图形都是matplotlib中的或变量,因此,如果多个线程同时处理不同的图形,一个线程可能会损坏另一个线程的变量。python threads类检测到并行的多个对象正在尝试访问同一个类并作出反应。它通常完成第一个线程并停止其他线程。在
在您的代码中,您永远不会关闭图1,因此无法在独立线程中创建图2,而不会冒着干扰的风险。所以你可以用一个线程来获取数据,用另一个线程对数据进行FFT,第三个线程可以绘图。绘图线程必须以这样一种方式工作:它将休眠,直到它在收集数据时被触发,以便将原始数据添加到图(1)中,然后在FFT结束时再次触发时,数据将添加到图(2)。(检查原始数据的新循环,然后检查FFT的新数据。仅当true时执行某些操作)(建议使用队列)由于它们不再是两个独立的线程,因此在运行另一个线程之前,您不再需要关闭其中一个线程。在
如果您确实想并行打印,请将matplotlib复制到具有新名称的文件中,并使用matplotlib打印一个地物,另一个图形使用matplotlib打印。在
恐怕这不是一个完全琐碎的代码,因为你说你是初学者。但话说回来,这不是一个完全微不足道的问题。这就是我的工作。从GUI线程调用'add'将事件(要执行的函数)放入队列,然后从图形线程调用'execute'在该线程上执行它们。如果您有多个图形线程,您将有多个队列。在
请注意,除了TaskQueue之外,还有一个循环调度程序任务环。您现在不需要它,但这只是一段生产代码,所以我已经将它一般地应用于多线程调度问题。在
相关问题 更多 >
编程相关推荐