問題描述
我有一個 PyQt 文件,只需單擊一個按鈕,它就會運行另一個 python 文件(我們稱之為 calc.py
)中的函數(shù),該文件執(zhí)行非常高級的計算并使用 matplotlib 進行繪圖結(jié)果.
I have a PyQt file that, on the click of a button, runs a function from another python file (let's call calc.py
) that carries out a really advanced calculation and uses matplotlib to plot the result.
我想在計算完成/生成圖形后,在 PyQt 窗口中顯示 calc.py
生成的這個圖.不過,鑒于計算和數(shù)字是在另一個文件中進行的,我不確定執(zhí)行此操作的最佳方法.
I would like to show this plot generated by calc.py
in the PyQt window after the calculation is complete/the figure is generated. Although, I'm not sure the best way to carry this out given that the calculation and figure are made in another file.
pyqt.py
import PyQt5 . . .
from calc import do_calc
class Window(QMainWindow):
def __init__(self, parent=None):
super(Window, self).__init__(parent)
self.title_label = QLabel("Label Text", self) #random label in top of window
###code here to display matplotlib plot in my PyQt app####
if __name__ == '__main__':
app = QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec_())
calc.py
import matplotlib.pyplot as plt
def do_calc():
plt.figure()
for i in x:
... #really complex calculation here
plt.plot()
plt.draw()
我一直在查看如何在 Qt 中顯示 matplotlib 圖的其他示例,但它們通常圍繞在 PyQt 文件或小部件類中進行的計算,在這種情況下我無法真正做到.我可以更改 calc.py
文件以返回項目或執(zhí)行任何其他可能有用的操作,但計算可能需要保留在該文件中,以便它可以獨立于 PyQt 運行
I've been looking at other examples of how to display matplotlib plots in Qt but they usually orient around the calculation being done in the PyQt file or widget class which I can't really do in this instance. I can alter the calc.py
file to return items or do anything else that might be helpful, but the calculations will likely need to stay in that file so it can be ran independently from the PyQt
推薦答案
解決方案是一個hack(將來可能會失敗)假設(shè)calc.py中matplotlib使用的后端使用PyQt5,為此需要先導(dǎo)入 PyQt5,再導(dǎo)入 calc.py.
The solution is a hack(may fail in the future) that assumes that the backend used by matplotlib in calc.py uses PyQt5, for this it is necessary to import PyQt5 first and then calc.py.
邏輯是使用plt.ion使matplotlib不阻塞eventloop,然后在以FigureCanvas作為centralWidget的頂層(窗口)中搜索.
The logic is to make matplotlib not block the eventloop using plt.ion, and then search among the toplevels (windows) that have a FigureCanvas as their centralWidget.
calc.py
import matplotlib.pyplot as plt
import numpy as np
def do_calc():
t = np.arange(0.0, 2.0, 0.01)
s = 1 + np.sin(2 * np.pi * t)
fig, ax = plt.subplots()
ax.plot(t, s)
ax.set(
xlabel="time (s)",
ylabel="voltage (mV)",
title="About as simple as it gets, folks",
)
ax.grid()
plt.show()
ma??in.py
import sys
from PyQt5.QtWidgets import QApplication, QLabel, QMainWindow, QVBoxLayout, QWidget
import matplotlib.pyplot as plt
from matplotlib.backends.backend_qt5agg import FigureCanvas
from calc import do_calc
class Window(QMainWindow):
def __init__(self, parent=None):
super(Window, self).__init__(parent)
self.title_label = QLabel("Label Text")
central_widget = QWidget()
self.setCentralWidget(central_widget)
lay = QVBoxLayout(central_widget)
lay.addWidget(self.title_label)
plt.ion()
do_calc()
for tl in QApplication.topLevelWidgets():
if isinstance(tl, QMainWindow) and isinstance(
tl.centralWidget(), FigureCanvas
):
lay.addWidget(tl)
if __name__ == "__main__":
app = QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec_())
另一個更好的選擇是獲取所有圖形,然后是畫布,最后是該畫布的窗口:
Another better option is to get all the Figures and then the canvas and finally the window of that canvas:
class Window(QMainWindow):
def __init__(self, parent=None):
super(Window, self).__init__(parent)
self.title_label = QLabel("Label Text")
central_widget = QWidget()
self.setCentralWidget(central_widget)
lay = QVBoxLayout(central_widget)
lay.addWidget(self.title_label)
plt.ion()
do_calc()
for i in plt.get_fignums():
canvas = plt.figure(i).canvas
if isinstance(canvas, QWidget):
lay.addWidget(canvas.window())
這篇關(guān)于顯示來自其他文件的 Matplotlib 圖的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網(wǎng)!