当我将 Qslitter 移动到带有 matplotlib 图形的边缘时,如何避免 PyQt5 崩溃?
How avoid PyQt5 to crash when I move Qslitter to the edge with a matplotlib figure in it?
我在 QSplitter 中有两个 matplotlib 图。
当我将 Splitter 移动到边缘时(图形消失),代码崩溃。
我得到的错误是
Traceback (most recent call last):
File "C:\Python36\lib\site-packages\matplotlib\backends\backend_qt5.py", line 397, in resizeEvent
self.figure.set_size_inches(winch, hinch, forward=False)
File "C:\Python36\lib\site-packages\matplotlib\figure.py", line 902, in set_size_inches
raise ValueError(f'figure size must be positive finite not {size}')
ValueError: figure size must be positive finite not [0. 6.12]
以前这不是问题,当屏幕上只有 Qsplitter 的两侧之一时,我的代码没有崩溃。当我再次将分离器拉到中间时,图形又正常出现了。
这里是一个最小的例子:
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
import sys
import matplotlib.pyplot as plt
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
class window(QMainWindow):
def __init__(self, parent=None):
super(window, self).__init__()
self.parent = parent
self.centralWidget = QWidget()
self.setCentralWidget(self.centralWidget)
self.mainHBOX_param_scene = QHBoxLayout()
self.mainsplitter = QSplitter(Qt.Horizontal)
V1 = Viewer()
V2 = Viewer()
self.mainsplitter.addWidget(V1)
self.mainsplitter.addWidget(V2)
self.mainHBOX_param_scene.addWidget(self.mainsplitter)
self.centralWidget.setLayout(self.mainHBOX_param_scene)
class Viewer(QGraphicsView):
def __init__(self, parent=None):
super( Viewer, self).__init__(parent)
self.parent = parent
self.setStyleSheet("border: 0px")
self.scene = QGraphicsScene(self)
self.setScene(self.scene)
self.figure = plt.figure()
self.canvas = FigureCanvas(self.figure)
self.axes_Delay = self.figure.add_subplot(1, 1,1)
self.axes_Delay.set_title("Title")
# self.canvas.setGeometry(0, 0, 1600, 500 )
layout = QVBoxLayout()
layout.addWidget(self.canvas)
self.setLayout(layout)
self.canvas.show()
def closeEvent(self, event):
plt.close(self.figure)
def main():
app = QApplication(sys.argv)
ex = window(app)
ex.show()
sys.exit(app.exec_( ))
if __name__ == '__main__':
main()
如何避免这个错误?
顺便说下我用的是matplotlib 3.2.1版本
很明显,这是一个 matplotlib 错误,它没有考虑到 resizeEvent 的大小可以 <=0,并且该信息用于通过关联的 Figure 进行绘制,从而导致此类错误。解决方法是重写resizeEvent方法:
class FixFigureCanvas(FigureCanvas):
def resizeEvent(self, event):
if event.size().width() <= 0 or event.size().height() <= 0:
return
super(FixFigureCanvas, self).resizeEvent(event)
# ...
self.figure = plt.figure()
<b>self.canvas = FixFigureCanvas(self.figure)</b>
self.axes_Delay = self.figure.add_subplot(1, 1, 1)
# ...
我在 QSplitter 中有两个 matplotlib 图。 当我将 Splitter 移动到边缘时(图形消失),代码崩溃。
我得到的错误是
Traceback (most recent call last):
File "C:\Python36\lib\site-packages\matplotlib\backends\backend_qt5.py", line 397, in resizeEvent
self.figure.set_size_inches(winch, hinch, forward=False)
File "C:\Python36\lib\site-packages\matplotlib\figure.py", line 902, in set_size_inches
raise ValueError(f'figure size must be positive finite not {size}')
ValueError: figure size must be positive finite not [0. 6.12]
以前这不是问题,当屏幕上只有 Qsplitter 的两侧之一时,我的代码没有崩溃。当我再次将分离器拉到中间时,图形又正常出现了。
这里是一个最小的例子:
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
import sys
import matplotlib.pyplot as plt
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
class window(QMainWindow):
def __init__(self, parent=None):
super(window, self).__init__()
self.parent = parent
self.centralWidget = QWidget()
self.setCentralWidget(self.centralWidget)
self.mainHBOX_param_scene = QHBoxLayout()
self.mainsplitter = QSplitter(Qt.Horizontal)
V1 = Viewer()
V2 = Viewer()
self.mainsplitter.addWidget(V1)
self.mainsplitter.addWidget(V2)
self.mainHBOX_param_scene.addWidget(self.mainsplitter)
self.centralWidget.setLayout(self.mainHBOX_param_scene)
class Viewer(QGraphicsView):
def __init__(self, parent=None):
super( Viewer, self).__init__(parent)
self.parent = parent
self.setStyleSheet("border: 0px")
self.scene = QGraphicsScene(self)
self.setScene(self.scene)
self.figure = plt.figure()
self.canvas = FigureCanvas(self.figure)
self.axes_Delay = self.figure.add_subplot(1, 1,1)
self.axes_Delay.set_title("Title")
# self.canvas.setGeometry(0, 0, 1600, 500 )
layout = QVBoxLayout()
layout.addWidget(self.canvas)
self.setLayout(layout)
self.canvas.show()
def closeEvent(self, event):
plt.close(self.figure)
def main():
app = QApplication(sys.argv)
ex = window(app)
ex.show()
sys.exit(app.exec_( ))
if __name__ == '__main__':
main()
如何避免这个错误? 顺便说下我用的是matplotlib 3.2.1版本
很明显,这是一个 matplotlib 错误,它没有考虑到 resizeEvent 的大小可以 <=0,并且该信息用于通过关联的 Figure 进行绘制,从而导致此类错误。解决方法是重写resizeEvent方法:
class FixFigureCanvas(FigureCanvas):
def resizeEvent(self, event):
if event.size().width() <= 0 or event.size().height() <= 0:
return
super(FixFigureCanvas, self).resizeEvent(event)
# ...
self.figure = plt.figure()
<b>self.canvas = FixFigureCanvas(self.figure)</b>
self.axes_Delay = self.figure.add_subplot(1, 1, 1)
# ...