Redraw Matplotlib帆布而无需悬挂/冷冻GUI
我正在研究实时绘制数据的应用程序。
我已经使用pyqt5创建GUI和matplotlib来创建图形。
GUI由一个带有多个选项卡的窗口组成。 当前有4个选项卡,所有选项卡都有网格布局。 网格为2x3,包含图形的小部件是 在位置(0,0),(0,1),(0,2)和(1,0)。
我正在单独的线程中解析数据并处理数据。 然后将数据传递到包含图形的小部件 并清除图形,然后重新绘制。
我相信悬挂/冻结是由于 重新刷新的主线程中包含我的GUI。 这是我从阅读其他问题中收集的,但是 我还没有看到针对给定问题的工作解决方案。
有什么办法可以在绘图过程中完成 单独的线程使其不会悬挂/冻结GUI?
如果没有解决方案,是否还有另一个绘图库是线程安全的,并且可以很好地替代我要做的事情?
我在找到解决这个问题的示例方面没有任何成功, 或我完全理解的良好答案来解决它。
这是一篇相关的帖子,我不理解提供的答案,因为我不能 获取执行代码。
matplotlib和pyqt4: 下面绘制另一个
是我当前拥有的示例。
from PyQt5 import QtWidgets
from PyQt5.QtCore import (
pyqtSignal,
QThread,
QObject,
)
import matplotlib.pyplot as plt
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
import sys
import time
import random
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self.tabWidget = QtWidgets.QTabWidget()
self.setCentralWidget(self.tabWidget)
self.tab1 = QtWidgets.QWidget()
self.tab1_layout = QtWidgets.QGridLayout()
GraphWidget_1 = GraphWidget()
GraphWidget_2 = GraphWidget()
GraphWidget_3 = GraphWidget()
GraphWidget_4 = GraphWidget()
self.tab1_layout.addWidget(GraphWidget_1, 0, 0)
self.tab1_layout.addWidget(GraphWidget_2, 0, 1)
self.tab1_layout.addWidget(GraphWidget_3, 1, 0)
self.tab1_layout.addWidget(GraphWidget_4, 1, 1)
self.tab1.setLayout(self.tab1_layout)
self.tabWidget.addTab(self.tab1, "Tab1")
class GraphWidget(QtWidgets.QWidget):
def __init__(self, parent = None):
super().__init__()
self.canvas = FigureCanvas(Figure())
vertical_layout = QtWidgets.QVBoxLayout(self)
vertical_layout.addWidget(self.canvas)
self.fig = plt.figure(figsize = (4,4), dpi = 100)
self.fig.set_tight_layout(True)
self.ax = self.fig.add_subplot(1, 1, 1)
self.canvas.figure = self.fig
self.worker_obj = Worker()
self.thread = QThread()
self.worker_obj.moveToThread(self.thread)
self.worker_obj.update_graph_signal.connect(self.update_graph)
self.thread.started.connect(self.worker_obj.perpetual_update)
self.thread.start()
def update_graph(self, x, y):
print('update')
self.ax.clear()
self.ax.plot(x, y, color="orange")
self.canvas.draw()
class Worker(QObject):
update_graph_signal = pyqtSignal(list, list)
def __init__(self):
super().__init__()
def perpetual_update(self):
while True:
time.sleep(5)
x = []
y = []
for i in range(0,3):
n = random.randint(1,30)
x.append(n)
n = random.randint(1,30)
y.append(n)
self.update_graph_signal.emit(x, y)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
window = MainWindow()
window.showMaximized()
sys.exit(app.exec())
I am working on an application that plots data in real time.
I've used PyQt5 to create the GUI and Matplotlib to create the graphs.
The GUI consists of a window with multiple tabs.
There are currently 4 tabs and all of them have a grid layout.
The grid is 2x3, and the widgets that contain the graphs are
in locations (0,0), (0,1), (0,2), and (1, 0).
I am parsing the data, and processing it, in a separate thread.
The data is then passed to the widget that contains the graphs
and the graphs are cleared and then redrawn.
I believe that the hang/freeze is due to the
redrawing that is done within the main thread which contains my GUI.
This is what I've gathered from reading other questions, but
I have not seen a working solution to the given problem.
Is there any way that the drawing process can be done within a
separate thread so that it does not hang/freeze the GUI?
If there is no solution, is there another plotting library that is thread-safe and would be a good substitute for what I am trying to do?
I have not had any success in finding examples that solve this problem,
or good answers that I fully understand to address it.
Here is a related post in which I do not understand the provided answer as I cannot
get the code to execute.
matplotlib and pyqt4: update plot in one thread, draw in another
Below is an example of what I currently have.
from PyQt5 import QtWidgets
from PyQt5.QtCore import (
pyqtSignal,
QThread,
QObject,
)
import matplotlib.pyplot as plt
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
import sys
import time
import random
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self.tabWidget = QtWidgets.QTabWidget()
self.setCentralWidget(self.tabWidget)
self.tab1 = QtWidgets.QWidget()
self.tab1_layout = QtWidgets.QGridLayout()
GraphWidget_1 = GraphWidget()
GraphWidget_2 = GraphWidget()
GraphWidget_3 = GraphWidget()
GraphWidget_4 = GraphWidget()
self.tab1_layout.addWidget(GraphWidget_1, 0, 0)
self.tab1_layout.addWidget(GraphWidget_2, 0, 1)
self.tab1_layout.addWidget(GraphWidget_3, 1, 0)
self.tab1_layout.addWidget(GraphWidget_4, 1, 1)
self.tab1.setLayout(self.tab1_layout)
self.tabWidget.addTab(self.tab1, "Tab1")
class GraphWidget(QtWidgets.QWidget):
def __init__(self, parent = None):
super().__init__()
self.canvas = FigureCanvas(Figure())
vertical_layout = QtWidgets.QVBoxLayout(self)
vertical_layout.addWidget(self.canvas)
self.fig = plt.figure(figsize = (4,4), dpi = 100)
self.fig.set_tight_layout(True)
self.ax = self.fig.add_subplot(1, 1, 1)
self.canvas.figure = self.fig
self.worker_obj = Worker()
self.thread = QThread()
self.worker_obj.moveToThread(self.thread)
self.worker_obj.update_graph_signal.connect(self.update_graph)
self.thread.started.connect(self.worker_obj.perpetual_update)
self.thread.start()
def update_graph(self, x, y):
print('update')
self.ax.clear()
self.ax.plot(x, y, color="orange")
self.canvas.draw()
class Worker(QObject):
update_graph_signal = pyqtSignal(list, list)
def __init__(self):
super().__init__()
def perpetual_update(self):
while True:
time.sleep(5)
x = []
y = []
for i in range(0,3):
n = random.randint(1,30)
x.append(n)
n = random.randint(1,30)
y.append(n)
self.update_graph_signal.emit(x, y)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
window = MainWindow()
window.showMaximized()
sys.exit(app.exec())
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论