窗口大小更改导致我的条形图覆盖 - Matplotlib
Posted
技术标签:
【中文标题】窗口大小更改导致我的条形图覆盖 - Matplotlib【英文标题】:Window size change causes an overwriting of my bar chart - Matplotlib 【发布时间】:2018-03-15 00:42:06 【问题描述】:我有一个用 PyQt5
制作的简单 GUI,带有两个 QWidgets
和两个按钮。每个按钮都会生成一个条形图。这部分工作完美,但是当窗口大小发生变化时,左侧条形图会覆盖右侧的条形图(即我有两次相同的条形图)。如何防止这种覆盖?
后端代码:
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
import matplotlib.pyplot as plt
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from network_view import Ui_MainWindow
import sys
class Run_script(QMainWindow, Ui_MainWindow):
def __init__(self,parent=None):
super(Run_script,self).__init__(parent)
self.setupUi(self)
self.pushButton1.clicked.connect(self.view_graph1)
self.pushButton2.clicked.connect(self.view_graph2)
self.figure = plt.figure()
self.graph1 = FigureCanvas(self.figure)
self.gridLayout.addWidget(self.graph1, 1, 0, 1, 1)
self.graph2 = FigureCanvas(self.figure)
self.gridLayout.addWidget(self.graph2, 1, 1, 1, 1)
def view_graph1(self):
self.figure.clf()
self.axes = self.figure.add_subplot(111)
x1 = [1, 2, 3, 4, 5]
y1 = [10, 20, 30, 40, 50]
x2 = [1.5, 2.5, 3.5, 4.5, 5.5]
y2 = [15, 25, 35, 45, 55]
self.axes.bar(x1,y1,width=0.40)
self.axes.bar(x2,y2,width=0.40)
self.graph1.draw()
def view_graph2(self):
self.figure.clf()
self.axes = self.figure.add_subplot(111)
x1 = [1, 2, 3, 4, 5]
y1 = [10, 20, 30, 40, 50]
x2 = [1.25, 2.25, 3.25, 4.25, 5.25]
y2 = [15, 25, 35, 45, 55]
x3 = [1.5, 2.5, 3.5, 4.5, 5.5]
y3 = [1, 2, 3, 4, 5]
self.axes.bar(x1,y1,width=0.40)
self.axes.bar(x2,y2,width=0.40)
self.axes.bar(x3,y3,width=0.40)
self.graph2.draw()
if __name__ == '__main__':
app = QApplication(sys.argv)
prog = Run_script()
prog.show()
sys.exit(app.exec_())
前端代码:
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(800, 600)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)
self.gridLayout.setObjectName("gridLayout")
self.pushButton1 = QtWidgets.QPushButton(self.centralwidget)
self.pushButton1.setObjectName("pushButton1")
self.gridLayout.addWidget(self.pushButton1, 0, 0, 1, 1)
self.pushButton2 = QtWidgets.QPushButton(self.centralwidget)
self.pushButton2.setObjectName("pushButton2")
self.gridLayout.addWidget(self.pushButton2, 0, 1, 1, 1)
self.widget1 = QtWidgets.QWidget(self.centralwidget)
self.widget1.setObjectName("widget1")
self.gridLayout.addWidget(self.widget1, 1, 0, 1, 1)
self.widget2 = QtWidgets.QWidget(self.centralwidget)
self.widget2.setObjectName("widget2")
self.gridLayout.addWidget(self.widget2, 1, 1, 1, 1)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 21))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.pushButton1.setText(_translate("MainWindow", "PushButton"))
self.pushButton2.setText(_translate("MainWindow", "PushButton"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
谢谢
【问题讨论】:
那是因为它们是相同的。您对两者都使用相同的数字。为了解决这个问题(1)不要在 PyQt GUI 中使用pyplot
(2)创建两个图形,每个图形画布一个。
【参考方案1】:
问题是因为你使用了相同的plt.figure()
,所以当你使用clf()
清理绘图并添加一个新绘图时,这就是你认为它被覆盖的原因。
为什么在按下按钮后没有立即看到效果?
因为它没有被通知给视图你必须应用更改,但是一旦你改变了它的大小,它就会用更新的数据重新绘制,你可以在使用update()
时看到同样的东西。
一个可能的解决方案是每个FigureCanvas
都有一个plt.figure()
:
class Run_script(QMainWindow, Ui_MainWindow):
def __init__(self,parent=None):
super(Run_script,self).__init__(parent)
self.setupUi(self)
self.pushButton1.clicked.connect(self.view_graph1)
self.pushButton2.clicked.connect(self.view_graph2)
self.figure1 = plt.figure()
self.graph1 = FigureCanvas(self.figure1)
self.gridLayout.addWidget(self.graph1, 1, 0, 1, 1)
self.figure2 = plt.figure()
self.graph2 = FigureCanvas(self.figure2)
self.gridLayout.addWidget(self.graph2, 1, 1, 1, 1)
def view_graph1(self):
self.figure1.clf()
axes = self.figure1.add_subplot(111)
x1 = [1, 2, 3, 4, 5]
y1 = [10, 20, 30, 40, 50]
x2 = [1.5, 2.5, 3.5, 4.5, 5.5]
y2 = [15, 25, 35, 45, 55]
axes.bar(x1,y1,width=0.40)
axes.bar(x2,y2,width=0.40)
self.graph1.draw()
def view_graph2(self):
self.figure2.clf()
axes = self.figure2.add_subplot(111)
x1 = [1, 2, 3, 4, 5]
y1 = [10, 20, 30, 40, 50]
x2 = [1.25, 2.25, 3.25, 4.25, 5.25]
y2 = [15, 25, 35, 45, 55]
x3 = [1.5, 2.5, 3.5, 4.5, 5.5]
y3 = [1, 2, 3, 4, 5]
axes.bar(x1,y1,width=0.40)
axes.bar(x2,y2,width=0.40)
axes.bar(x3,y3,width=0.40)
self.graph2.draw()
更好的实现是创建自己的画布:
class MyCanvas(FigureCanvas):
def __init__(self, *args, **kwargs):
self.figure = plt.figure()
FigureCanvas.__init__(self, self.figure)
class Run_script(QMainWindow, Ui_MainWindow):
def __init__(self,parent=None):
super(Run_script,self).__init__(parent)
self.setupUi(self)
self.pushButton1.clicked.connect(self.view_graph1)
self.pushButton2.clicked.connect(self.view_graph2)
self.graph1 = MyCanvas()
self.gridLayout.addWidget(self.graph1, 1, 0, 1, 1)
self.graph2 = MyCanvas()
self.gridLayout.addWidget(self.graph2, 1, 1, 1, 1)
def view_graph1(self):
self.graph1.figure.clf()
axes = self.graph1.figure.add_subplot(111)
x1 = [1, 2, 3, 4, 5]
y1 = [10, 20, 30, 40, 50]
x2 = [1.5, 2.5, 3.5, 4.5, 5.5]
y2 = [15, 25, 35, 45, 55]
axes.bar(x1,y1,width=0.40)
axes.bar(x2,y2,width=0.40)
self.graph1.draw()
def view_graph2(self):
self.graph2.figure.clf()
axes = self.graph2.figure.add_subplot(111)
x1 = [1, 2, 3, 4, 5]
y1 = [10, 20, 30, 40, 50]
x2 = [1.25, 2.25, 3.25, 4.25, 5.25]
y2 = [15, 25, 35, 45, 55]
x3 = [1.5, 2.5, 3.5, 4.5, 5.5]
y3 = [1, 2, 3, 4, 5]
axes.bar(x1,y1,width=0.40)
axes.bar(x2,y2,width=0.40)
axes.bar(x3,y3,width=0.40)
self.graph2.draw()
【讨论】:
【参考方案2】:正如已经评论的那样,您在程序中只有一个数字。因此,两个地块是相同的。你需要有两个不同的数字。此外,不要在 GUI 中使用 pyplot,因为这会让你很容易遇到这样的问题。
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from matplotlib.figure import Figure
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
class Run_script(QMainWindow, Ui_MainWindow):
def __init__(self,parent=None):
super(Run_script,self).__init__(parent)
self.setupUi(self)
self.pushButton1.clicked.connect(self.view_graph1)
self.pushButton2.clicked.connect(self.view_graph2)
self.figure1 = Figure()
self.graph1 = FigureCanvas(self.figure1)
self.gridLayout.addWidget(self.graph1, 1, 0, 1, 1)
self.figure2 = Figure()
self.graph2 = FigureCanvas(self.figure2)
self.gridLayout.addWidget(self.graph2, 1, 1, 1, 1)
def view_graph1(self):
self.figure1.clf()
self.axes = self.figure1.add_subplot(111)
x1 = [1, 2, 3, 4, 5]
y1 = [10, 20, 30, 40, 50]
x2 = [1.5, 2.5, 3.5, 4.5, 5.5]
y2 = [15, 25, 35, 45, 55]
self.axes.bar(x1,y1,width=0.40)
self.axes.bar(x2,y2,width=0.40)
self.graph1.draw()
def view_graph2(self):
self.figure2.clf()
self.axes = self.figure2.add_subplot(111)
x1 = [1, 2, 3, 4, 5]
y1 = [10, 20, 30, 40, 50]
x2 = [1.25, 2.25, 3.25, 4.25, 5.25]
y2 = [15, 25, 35, 45, 55]
x3 = [1.5, 2.5, 3.5, 4.5, 5.5]
y3 = [1, 2, 3, 4, 5]
self.axes.bar(x1,y1,width=0.40)
self.axes.bar(x2,y2,width=0.40)
self.axes.bar(x3,y3,width=0.40)
self.graph2.draw()
【讨论】:
以上是关于窗口大小更改导致我的条形图覆盖 - Matplotlib的主要内容,如果未能解决你的问题,请参考以下文章