python - 使用 Figure() 对象更新 FigureCanvasQTAgg 画布
问题描述
我有一个 GUI,它有一个带有按钮的主窗口和一个带有默认图的 FigureCanvasQTAgg 画布(只是一些默认的散点)。按钮单击命令应使用 Figure() 对象作为参数更改画布。我想知道如何构造这样的函数来接收 Figure() 对象并更新画布。教程总是处理自行创建图形的更新函数,但在我的情况下,这样的更新函数应该接收图形(在 GUI 类之外计算)作为参数。下面你可以看到我的(可能是伪的)代码
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import QRunnable, QThreadPool
from PyQt5.QtCore import *
import queue as Queue
import matplotlib.pyplot as plt
from matplotlib.figure import Figure
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas, NavigationToolbar2QT as NavigationToolbar
import os, sys
import psutil
# Back up the reference to the exceptionhook
sys._excepthook = sys.excepthook
def my_exception_hook(exctype, value, traceback):
# Print the error and traceback
print(exctype, value, traceback)
# Call the normal Exception hook after
sys._excepthook(exctype, value, traceback)
sys.exit(1)
# Set the exception hook to our wrapping function
sys.excepthook = my_exception_hook
def create_graph():
ax = Figure().add_subplot ( 111 )
ax.plot ( [1 , 2 , 3 , 4] , [10 , 20 , 25 , 30] , color = 'lightblue' , linewidth = 3 )
return ax
class Worker(QRunnable):
def __init__(self , queue):
QRunnable.__init__ ( self )
self.queue = queue
@pyqtSlot()
def run(self):
ax = create_graph()
self.queue.put ( ax ) ### transport ax object to GUI class
class Canvas ( FigureCanvas ):
def __init__(self, parent, figure):
self.fig = figure
FigureCanvas.__init__ ( self , self.fig )
self.setParent ( parent )
class GUI (QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self.setupUi(self)
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(1800, 900)
MainWindow.move(40,20)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.fig , axes = plt.subplots ( 1 , 1 )
plt.scatter ( [0 , 1 , 2 , 3 , 4 , 5] , [3 , 11 , 15 , 0 , 1 , 19] )
self.canvas = Canvas(self, self.fig)
self.canvas.setGeometry ( QtCore.QRect ( 30 , 400 , 811 , 381 ) )
MainWindow.setCentralWidget(self.centralwidget)
self.startButton = QtWidgets.QPushButton(self.centralwidget)
self.startButton.setGeometry(QtCore.QRect(270, 310, 261, 51))
self.startButton.clicked.connect(self.startCalc)
self.startButton.setText('Press me to redraw graph')
def startCalc(self):
self.queue = Queue.Queue ()
self.threadpool = QThreadPool ()
print ( "Multithreading with maximum %d threads" % self.threadpool.maxThreadCount () )
worker = Worker (self.queue)
self.threadpool.start ( worker )
QtCore.QTimer.singleShot ( 500 , self.process_queue )
def process_queue(self):
try:
msg = self.queue.get ( 0 ) ### here we have our ax object
self.fig.clear()
# Here I dont know how to re-draw self.canvas widget with new data (ax)
#Usualy one should create ax object right before canvas.draw function, but I have my ax object returned from outside the GUI class ... :((
self.canvas.draw ()
except Queue.Empty:
# print('empty')
QtCore.QTimer.singleShot ( 500 , self.process_queue )
def main():
global window
app = QtWidgets.QApplication ( sys.argv ) # Новый экземпляр QApplication
window = GUI () # Создаём объект класса ExampleApp
window.show () # Показываем окно
try:
sys.exit ( app.exec_ () )
except:
print ( "Exiting" )
if __name__ == '__main__': # Если мы запускаем файл напрямую, а не импортируем
main () # то запускаем функцию main()
解决方案
推荐阅读
- css - 背景附件:修复了如何使图像“不全屏”?
- python - Tkinter 按钮功能无法正常工作
- javascript - React Google Charts 烛台颜色和灯芯未显示
- c# - 当我的数据库出现错误时,如何使用 Visual Studio 运行我的代码?
- python - 如何将keras后端从tenserflow切换到theano?
- matlab - 比较两个符号表达式
- php - 如何为 PHP 8 设置 VS Code 扩展 Intelephense?
- node.js - 使用 multer memoryStorage 时如何重命名我的原始名称?
- spring-boot - 将 Redis 用作 Spring Session 缓存时如何最小化与 Redis 的交互?
- vue.js - Vue.js 3 卸载和内存泄漏