나는 유사한 문제에 직면하고있다. 그러나 결국 나는 나의 실시간 음모가 작동했다!
나는 내 코드를 살펴보고 관련없는 모든 것을 버렸습니다. 따라서 여기에서 알 수있는 것은 라이브 그래프를 표시하는 데 필요한 기본 코드입니다.
###################################################################
# #
# PLOTTING A LIVE GRAPH #
# ---------------------------- #
# EMBED A MATPLOTLIB ANIMATION INSIDE YOUR #
# OWN GUI! #
# #
###################################################################
import sys
import os
from PyQt4 import QtGui
from PyQt4 import QtCore
import functools
import numpy as np
import random as rd
import matplotlib
matplotlib.use("Qt4Agg")
from matplotlib.figure import Figure
from matplotlib.animation import TimedAnimation
from matplotlib.lines import Line2D
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
import time
import threading
def setCustomSize(x, width, height):
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(x.sizePolicy().hasHeightForWidth())
x.setSizePolicy(sizePolicy)
x.setMinimumSize(QtCore.QSize(width, height))
x.setMaximumSize(QtCore.QSize(width, height))
''''''
class CustomMainWindow(QtGui.QMainWindow):
def __init__(self):
super(CustomMainWindow, self).__init__()
# Define the geometry of the main window
self.setGeometry(300, 300, 800, 400)
self.setWindowTitle("my first window")
# Create FRAME_A
self.FRAME_A = QtGui.QFrame(self)
self.FRAME_A.setStyleSheet("QWidget { background-color: %s }" % QtGui.QColor(210,210,235,255).name())
self.LAYOUT_A = QtGui.QGridLayout()
self.FRAME_A.setLayout(self.LAYOUT_A)
self.setCentralWidget(self.FRAME_A)
# Place the zoom button
self.zoomBtn = QtGui.QPushButton(text = 'zoom')
setCustomSize(self.zoomBtn, 100, 50)
self.zoomBtn.clicked.connect(self.zoomBtnAction)
self.LAYOUT_A.addWidget(self.zoomBtn, *(0,0))
# Place the matplotlib figure
self.myFig = CustomFigCanvas()
self.LAYOUT_A.addWidget(self.myFig, *(0,1))
# Add the callbackfunc to ..
myDataLoop = threading.Thread(name = 'myDataLoop', target = dataSendLoop, daemon = True, args = (self.addData_callbackFunc,))
myDataLoop.start()
self.show()
''''''
def zoomBtnAction(self):
print("zoom in")
self.myFig.zoomIn(5)
''''''
def addData_callbackFunc(self, value):
# print("Add data: " + str(value))
self.myFig.addData(value)
''' End Class '''
class CustomFigCanvas(FigureCanvas, TimedAnimation):
def __init__(self):
self.addedData = []
print(matplotlib.__version__)
# The data
self.xlim = 200
self.n = np.linspace(0, self.xlim - 1, self.xlim)
a = []
b = []
a.append(2.0)
a.append(4.0)
a.append(2.0)
b.append(4.0)
b.append(3.0)
b.append(4.0)
self.y = (self.n * 0.0) + 50
# The window
self.fig = Figure(figsize=(5,5), dpi=100)
self.ax1 = self.fig.add_subplot(111)
# self.ax1 settings
self.ax1.set_xlabel('time')
self.ax1.set_ylabel('raw data')
self.line1 = Line2D([], [], color='blue')
self.line1_tail = Line2D([], [], color='red', linewidth=2)
self.line1_head = Line2D([], [], color='red', marker='o', markeredgecolor='r')
self.ax1.add_line(self.line1)
self.ax1.add_line(self.line1_tail)
self.ax1.add_line(self.line1_head)
self.ax1.set_xlim(0, self.xlim - 1)
self.ax1.set_ylim(0, 100)
FigureCanvas.__init__(self, self.fig)
TimedAnimation.__init__(self, self.fig, interval = 50, blit = True)
def new_frame_seq(self):
return iter(range(self.n.size))
def _init_draw(self):
lines = [self.line1, self.line1_tail, self.line1_head]
for l in lines:
l.set_data([], [])
def addData(self, value):
self.addedData.append(value)
def zoomIn(self, value):
bottom = self.ax1.get_ylim()[0]
top = self.ax1.get_ylim()[1]
bottom += value
top -= value
self.ax1.set_ylim(bottom,top)
self.draw()
def _step(self, *args):
# Extends the _step() method for the TimedAnimation class.
try:
TimedAnimation._step(self, *args)
except Exception as e:
self.abc += 1
print(str(self.abc))
TimedAnimation._stop(self)
pass
def _draw_frame(self, framedata):
margin = 2
while(len(self.addedData) > 0):
self.y = np.roll(self.y, -1)
self.y[-1] = self.addedData[0]
del(self.addedData[0])
self.line1.set_data(self.n[ 0 : self.n.size - margin ], self.y[ 0 : self.n.size - margin ])
self.line1_tail.set_data(np.append(self.n[-10:-1 - margin], self.n[-1 - margin]), np.append(self.y[-10:-1 - margin], self.y[-1 - margin]))
self.line1_head.set_data(self.n[-1 - margin], self.y[-1 - margin])
self._drawn_artists = [self.line1, self.line1_tail, self.line1_head]
''' End Class '''
# You need to setup a signal slot mechanism, to
# send data to your GUI in a thread-safe way.
# Believe me, if you don't do this right, things
# go very very wrong..
class Communicate(QtCore.QObject):
data_signal = QtCore.pyqtSignal(float)
''' End Class '''
def dataSendLoop(addData_callbackFunc):
# Setup the signal-slot mechanism.
mySrc = Communicate()
mySrc.data_signal.connect(addData_callbackFunc)
# Simulate some data
n = np.linspace(0, 499, 500)
y = 50 + 25*(np.sin(n/8.3)) + 10*(np.sin(n/7.5)) - 5*(np.sin(n/1.5))
i = 0
while(True):
if(i > 499):
i = 0
time.sleep(0.1)
mySrc.data_signal.emit(y[i]) # <- Here you emit a signal!
i += 1
###
###
if __name__== '__main__':
app = QtGui.QApplication(sys.argv)
QtGui.QApplication.setStyle(QtGui.QStyleFactory.create('Plastique'))
myGUI = CustomMainWindow()
sys.exit(app.exec_())
''''''
그냥 시도해보십시오. 이 코드를 복사하여 새로운 파이썬 파일에 붙여넣고 실행하십시오. 당신은 아름다운 부드러운 라이브 그래프를 얻어야한다 :
정말 고마워. 정말 깔끔한 응용 프로그램을 만들었습니다 :) PyQt4 플롯 위젯보다 Matplotlib 캔버스를 사용하는 것으로 나타났습니다. 당신이 PyQt4에 성공하지 못했기 때문입니까? 필자는 PyQt4의 주된 특징 중 하나가 실시간 데이터를 플롯 할 수 있다는 인상을 받았지만 위젯에서는 그렇지 않다. 나는 또한 당신의 코드에서 스레드 안전 방법을 사용하지 않는다면 일이 매우 잘못 될 것이라고 말했습니까? 위험은 무엇입니까? 나는 Rpi에 연결된 온도 센서로부터 데이터 신호를받을 것이다. 이 답변을 주셔서 감사합니다, 그것은 매우 유용합니다 :) – alkey
안녕 앨런 키. matplotlib 라이브러리는 모든 종류의 애니메이션 제작에 대한 놀라운 지원을 제공합니다. 그리고 그 코드는 그래프가 매끄럽도록 최적화되어 있습니다. 나를 위해, 그것은 중요합니다 :-). 글쎄, 스레드 안전하지 않은 방법에 대해, 나는 "스레드 안전"내 코드를 만들기 전에 한 번 이상한 오류 메시지가있었습니다. 관심이 있다면 나는 너를 찾아 볼 수있다. 어쨌든 내가 제시 한 코드는 100 % 스레드로부터 안전합니다. 0.1 초마다 새로운 데이터 포인트가 그래프로 보내지는 것을 보셨습니까? 신호 슬롯 메커니즘을 통해 '방출'됩니다. 온도 데이터를 보내면 (대신에 .. –
.. 내가 생성하는 부비동 기능), 온도 그래프를 볼 수 있습니다! 저를 믿으십시오, 나는 마이크로 제어기에서 동시에 오는 12 개의 신호로 그것을했다. 원자력 발전소의 제어판을 보는 것처럼 모든 12 개의 신호가 부드럽게 움직입니다 ;-) –