【问题标题】:Display Matplotlib plots from Other File显示来自其他文件的 Matplotlib 图
【发布时间】:2021-10-17 01:28:15
【问题描述】:

我有一个 PyQt 文件,只需单击一个按钮,它就会从另一个 python 文件(我们称之为 calc.py)运行一个函数,该文件执行非常高级的计算并使用 matplotlib 绘制结果。

我想在计算完成/图形生成后在 PyQt 窗口中显示由calc.py 生成的这个图。不过,鉴于计算和数字是在另一个文件中进行的,我不确定执行此操作的最佳方法。

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()

我一直在查看other examples 如何在 Qt 中显示 matplotlib 图,但它们通常围绕在 PyQt 文件或小部件类中进行的计算,在这种情况下我无法真正做到。我可以更改 calc.py 文件以返回项目或执行任何其他可能有用的操作,但计算可能需要保留在该文件中,以便它可以独立于 PyQt 运行

【问题讨论】:

    标签: python matplotlib pyqt pyqt5


    【解决方案1】:

    解决方案是一个 hack(将来可能会失败),它假设 matplotlib 在 calc.py 中使用的后端使用 PyQt5,为此需要先导入 PyQt5,然后再导入 calc.py。

    逻辑是使用plt.ion使matplotlib不阻塞eventloop,然后在以FigureCanvas作为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_())
    

    另一个更好的选择是获取所有图形,然后是画布,最后是该画布的窗口:

    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())
    

    【讨论】:

    • 完全如我所愿,谢谢!!
    猜你喜欢
    • 2021-06-18
    • 2012-02-27
    • 1970-01-01
    • 1970-01-01
    • 2011-12-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多