Python 使用 Qt Designer 表单和 PyQt5 在 QWidget 中绘制 matplotlib 图
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/43947318/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Plotting matplotlib figure inside QWidget using Qt Designer form and PyQt5
提问by launchpadmcquack
I don't understand the best way to link a matplotlib figure to a form created from Qt Designer. I have a form I created in QtDesigner and then compiled to python through pyuic5. My main program is:
我不明白将 matplotlib 图形链接到从 Qt Designer 创建的表单的最佳方法。我有一个在 QtDesigner 中创建的表单,然后通过 pyuic5 编译为 python。我的主要程序是:
import app_framework as af
import matplotlib
from PyQt5 import QtWidgets
import sys
matplotlib.use('Qt5Agg')
app = QtWidgets.QApplication(sys.argv)
form = af.MyApp()
form.show()
app.exec_()
where myApp calls the app_framework.py form created from Qt Designer then converted by pyuic5 (design.py):
其中 myApp 调用从 Qt Designer 创建的 app_framework.py 表单,然后由 pyuic5 (design.py) 转换:
from PyQt5.QtWidgets import QApplication, QMainWindow
import design
class MyApp(QMainWindow, design.Ui_mainWindow):
def __init(self):
super(self.__class__, self).__init__()
<button initializations>
<function definitions for button callbacks>
I'm confused as to where in this framework I can link a matplotlib figure to a premade empty widget in QtDesigner, or something of that sort, so that I can plot new data in the GUI window as things happen (text entered, button push, etc.)
我很困惑在这个框架中我可以将 matplotlib 图形链接到 QtDesigner 中的预制空小部件或类似的东西,以便我可以在事件发生时在 GUI 窗口中绘制新数据(输入文本,按钮按下, 等等。)
I've found some threads here on SOand matplotlib's site, but I'm not sure I understand the correct process for creating the space for this widget in the Qt Designer form then linking a plot, and/or creating a widget post hoc and then linking and plotting.
我在SO和matplotlib 的网站上找到了一些线程,但我不确定我是否理解在 Qt 设计器表单中为这个小部件创建空间然后链接绘图和/或创建小部件的正确过程和/或然后链接和绘图。
What I've done so far is create an empty QWidget inside Qt Creator and then after pyuic5 compile, I alter the design.py file as follows:
到目前为止,我所做的是在 Qt Creator 中创建一个空的 QWidget,然后在 pyuic5 编译后,我更改 design.py 文件如下:
from PyQt5 import QtCore, QtGui, QtWidgets
# **** ADDED THIS
from matplotlib.figure import Figure
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as Canvas
# ****
class Ui_mainWindow(object):
def setupUi(self, mainWindow):
<mainWindow setup stuff>
self.centralwidget = QtWidgets.QWidget(mainWindow)
# ****ALTERED THIS FROM self.plotWidget = QtWidgets.QWidget(self.centralWidget)
self.plotWidget = MplWidget(self.centralWidget)
# *****
self.plotWidget.setGeometry(QtCore.QRect(20, 250, 821, 591))
self.plotWidget.setObjectName("plotWidget")
# **** ADDED THIS
class MplCanvas(Canvas):
def __init__(self):
self.fig = Figure()
self.ax = self.fig.add_subplot(111)
Canvas.__init__(self, self.fig)
Canvas.setSizePolicy(self, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
Canvas.updateGeometry(self)
class MplWidget(QtWidgets.QWidget):
def __init__(self, parent=None):
QtWidgets.QWidget.__init__(self, parent)
self.canvas = MplCanvas()
# ***********
and then app_framework.py as:
然后 app_framework.py 为:
from PyQt5.QtWidgets import QApplication, QMainWindow
import design
class MyApp(QMainWindow, design.Ui_mainWindow):
def __init(self):
super(self.__class__, self).__init__()
self.setupUi(self)
self.pushButton_plotData.clicked.connect(self.plot_data)
def plot_data(self):
x=range(0, 10)
y=range(0, 20, 2)
self.plotWidget.canvas.ax.plot(x, y)
self.plotWidget.canvas.draw()
I thought this would work, but when I click the plot push button, nothing happens. It doesn't lock up, it just doesn't plot anything. I'm guessing I'm missing something fundamental for plotting a matplotlib figure and/or canvas in this empty widget.
我认为这会起作用,但是当我单击绘图按钮时,什么也没有发生。它不会锁定,它只是不绘制任何内容。我猜我错过了在这个空的小部件中绘制 matplotlib 图形和/或画布的基本内容。
采纳答案by launchpadmcquack
I found the solution through the help of this SO post, which links to this free sample chapterof a book I'm probably gonna need to buy. As sort of mentioned in a number of other posts, one needs to "Promote" the blank QtWidget to a MplWidget using the header mplwidget. After doing this, and then running the pyuic5 command, "from mplwidget import MplWidget" will appear in the design.py file which can be updated anytime without worry about overwritting. Then, create an mplwidget.py file with:
我通过这篇SO post的帮助找到了解决方案,它链接到我可能需要购买的一本书的免费示例章节。正如在许多其他帖子中提到的那样,需要使用标题 mplwidget 将空白 QtWidget“提升”为 MplWidget。这样做之后,然后运行 pyuic5 命令,“from mplwidget import MplWidget”将出现在 design.py 文件中,该文件可以随时更新,无需担心覆盖。然后,创建一个 mplwidget.py 文件:
# Imports
from PyQt5 import QtWidgets
from matplotlib.figure import Figure
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as Canvas
import matplotlib
# Ensure using PyQt5 backend
matplotlib.use('QT5Agg')
# Matplotlib canvas class to create figure
class MplCanvas(Canvas):
def __init__(self):
self.fig = Figure()
self.ax = self.fig.add_subplot(111)
Canvas.__init__(self, self.fig)
Canvas.setSizePolicy(self, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
Canvas.updateGeometry(self)
# Matplotlib widget
class MplWidget(QtWidgets.QWidget):
def __init__(self, parent=None):
QtWidgets.QWidget.__init__(self, parent) # Inherit from QWidget
self.canvas = MplCanvas() # Create canvas object
self.vbl = QtWidgets.QVBoxLayout() # Set box for plotting
self.vbl.addWidget(self.canvas)
self.setLayout(self.vbl)
Then, the app framework can be as I had earlier. When run, and pushing the plot button, the figure appears as expected. I think I basically had done everything to "Promote" the QWidget by hand just missing the vbl stuff, but all that would be overwritten everytime the Qt Designer form is editted.
然后,应用程序框架可以和我之前一样。运行并按下绘图按钮时,图形会按预期显示。我想我基本上已经完成了手动“推广”QWidget 的所有工作,只是缺少 vbl 的东西,但是每次编辑 Qt Designer 表单时所有这些都会被覆盖。
app_framework.py:
app_framework.py:
from PyQt5.QtWidgets import QApplication, QMainWindow
import design
class MyApp(QMainWindow, design.Ui_mainWindow):
def __init(self):
super(self.__class__, self).__init__()
self.setupUi(self)
self.pushButton_plotData.clicked.connect(self.plot_data)
def plot_data(self):
x=range(0, 10)
y=range(0, 20, 2)
self.plotWidget.canvas.ax.plot(x, y)
self.plotWidget.canvas.draw()
main.py:
主要.py:
from PyQt5 import QtWidgets
import sys
# Local Module Imports
import app_framework as af
# Create GUI application
app = QtWidgets.QApplication(sys.argv)
form = af.MyApp()
form.show()
app.exec_()