我正在使用PyQt4和matplotlib制作一个gui。我发现this非常有用的问题/答案,我正在尝试使用标签式gui窗口。一切似乎都很好(有一些小的调整);但是,每当我关闭主窗口时,我都会出现“Python意外退出”错误以及分段错误。虽然这不会影响程序的运行,但它很烦人,我想解决这个问题。
现在,在试图弄清楚发生了什么的时候,我得到了下面的MWE(或者如果你愿意的话,最小的例子)
import sys
import matplotlib
matplotlib.use('Qt4agg')
import matplotlib.pyplot as plt
import numpy as np
from PyQt4 import QtCore
from PyQt4 import QtGui as qt
if __name__ == "__main__":
fig = plt.figure()
x, y = np.random.randn(2, 40)
ax = fig.add_subplot(111)
ax.plot(x, y, 'o')
ax.hold(False)
app = qt.QApplication(sys.argv)
# ui = MplMultiTab(figures=[fig], labels=["yay"])
ui = qt.QMainWindow()
ui.main_frame = qt.QWidget()
vbox = qt.QVBoxLayout()
vbox.addWidget(fig.canvas)
ui.main_frame.setLayout(vbox)
ui.setCentralWidget(ui.main_frame)
ui.show()
sys.exit(app.exec_())
问题似乎是将图形画布添加到窗口,好像我不这样做而是制作一个空的gui(删除vbox.addWidget(fig.canvas)
)一切都很好并且没有段错误。
任何人都可以看到出现问题或是matplotlib或pyqt中的错误吗?同样有趣的是,如果我设置我的gui类似于this answer,那么我没有分段错误,但我无法弄清楚它们之间的区别是什么。
对于每个人的信息,我在python 3.5.2上使用Pyxt verion 4.11.4和OSX 10.11.6上的matplotlib 1.5.3版运行它。
答案 0 :(得分:3)
如PyQt documentation中所述:
对于使用Qt的任何GUI应用程序,无论应用程序在任何给定时间是否具有0,1,2或更多窗口,都只有一个QApplication对象。
我认为这里最有可能发生的是QApplication在生成数字时由pyplot静默创建。此QApplication用于管理FigureManager的主事件循环,这是由pyplot创建的GUI,用于在屏幕上显示图形。
因此,由于已经使用pyplot创建了QApplication,我认为在代码中进一步调用qt.QApplication(sys.argv)
时通常会引发错误,但有些Qt似乎没有看到并允许创建另一个QApplication。这可能是在尝试关闭应用程序时导致冲突的原因。我看到3个不同的选项来解决这个问题:
1 - 将pyplot代码放入QApplication中,以便pyplot看到它并使用它而不是构建自己的代码:
import sys
import matplotlib
matplotlib.use('Qt4agg')
import matplotlib.pyplot as plt
import numpy as np
from PyQt4 import QtGui as qt
if __name__ == '__main__':
app = qt.QApplication(sys.argv)
fig, ax = plt.subplots()
x, y = np.random.randn(2, 40)
ax.plot(x, y, 'o')
ui = qt.QWidget()
vbox = qt.QVBoxLayout()
vbox.addWidget(fig.canvas)
ui.setLayout(vbox)
ui.show()
sys.exit(app.exec_())
2 - 使用指向已由pyplot构建的QApplication的指针,而不是创建一个新指针:
import sys
import matplotlib
matplotlib.use('Qt4agg')
import matplotlib.pyplot as plt
import numpy as np
from PyQt4 import QtGui as qt
if __name__ == '__main__':
fig, ax = plt.subplots()
x, y = np.random.randn(2, 40)
ax.plot(x, y, 'o')
app = qt.QApplication.instance()
ui = qt.QWidget()
vbox = qt.QVBoxLayout()
vbox.addWidget(fig.canvas)
ui.setLayout(vbox)
ui.show()
sys.exit(app.exec_())
3 - 正如matplotlib documentation中所建议的那样,在Qt接口中嵌入mpl图时避免使用pyplot接口,而是使用面向对象的API。在这种情况下,您的MWE可以重写为:
import sys
import matplotlib
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg
import numpy as np
from PyQt4 import QtGui as qt
if __name__ == '__main__':
app = qt.QApplication(sys.argv)
fig = matplotlib.figure.Figure()
canvas = FigureCanvasQTAgg(fig)
ax = fig.add_subplot(111)
x, y = np.random.randn(2, 40)
ax.plot(x, y, 'o')
ui = qt.QWidget()
vbox = qt.QVBoxLayout()
vbox.addWidget(canvas)
ui.setLayout(vbox)
ui.show()
sys.exit(app.exec_())