MNE/Matplotlib可视化导致easygui-qt脚本退出问题咨询
问题:整合MNE、Matplotlib与easygui-qt时脚本提前退出,无法执行后续代码
我在整合MNE、Matplotlib与easygui-qt时遇到故障,无法准确定位根源。需求是:展示MNE生成的交互式图形,同时用easygui-qt弹出模态弹窗,允许用户操作图形后通过弹窗提交输入。但生成图形时Matplotlib会开启交互模式,导致用户完成弹窗输入后脚本直接退出,后续代码无法执行。
示例代码
import matplotlib import mne from mne.datasets import sample from mne.io import read_raw_fif import easygui_qt.easygui_qt as gui import matplotlib.pyplot as plt matplotlib.use('Qt5Agg') mne.viz.set_browser_backend('qt') # or "matplotlib" fname = sample.data_path() / "MEG" / "sample" / "sample_audvis_raw.fif" raw = read_raw_fif(fname, preload=False, verbose=False) raw.crop(0, 60).pick("eeg") raw.load_data(verbose=False) input1 = gui.get_continue_or_cancel(title="Input 1", message="", continue_button_text="T", cancel_button_text="F") fig = raw.plot(verbose=False, show=True) # can set show=False with same downstream effect # plt.ioff() # this has no effect # matplotlib.interactive(False) # this has no effect input2 = gui.get_continue_or_cancel(title="Input 2", message="", continue_button_text="T", cancel_button_text="F") print(f"In 1: {input1}\t\tIn 2: {input2}")
环境信息
包版本
matplotlib:3.8.4 PyQt5: 5.15.11 easygui-qt: 0.9.3 mne: 1.9.0 mne-qt-browser: 0.6.3
系统信息
>>> mne.sys_info() Platform Windows-11-10.0.26100-SP0 Python 3.12.3 (tags/v3.12.3:f6650f9, Apr 9 2024, 14:05:25) [MSC v.1938 64 bit (AMD64)] Executable C:\Path\To\venv\Scripts\python.exe CPU 13th Gen Intel(R) Core(TM) i7-13700 (24 cores) Memory 63.7 GiB Core + mne 1.9.0 (latest release) + numpy 2.1.1 (OpenBLAS 0.3.27 with 24 threads) + scipy 1.15.1 + matplotlib 3.8.4Backend QtAgg is interactive backend. Turning interactive mode on. (backend=QtAgg) Numerical (optional) + sklearn 1.6.1 + pandas 2.2.3 + h5py 3.12.1 - unavailable numba, nibabel, nilearn, dipy, openmeeg, cupy, h5io Visualization (optional) + qtpy 2.4.3 (PyQt6=6.8.2) + pyqtgraph 0.13.7 + mne-qt-browser 0.6.3 - unavailable pyvista, pyvistaqt, vtk, ipympl, ipywidgets, trame_client, trame_server, trame_vtk, trame_vuetify Ecosystem (optional) + mne-icalabel 0.7.0 - unavailable mne-bids, mne-nirs, mne-features, mne-connectivity, mne-bids-pipeline, neo, eeglabio, edfio, mffpy, pybv
解决方案
原因分析
MNE的Qt后端浏览器(mne-qt-browser)基于PyQtGraph运行,独立于Matplotlib的事件循环。当调用raw.plot()时,它会临时启动Qt事件循环,但弹窗关闭后事件循环终止,导致脚本直接退出。手动关闭Matplotlib交互模式无效,因为MNE的Qt绘图不依赖Matplotlib的事件系统。
解决方法:手动管理Qt事件循环
通过QApplication统一控制Qt事件循环,确保图形窗口和弹窗都能正常运行,且脚本不会提前退出。修改后的代码如下:
import matplotlib import mne from mne.datasets import sample from mne.io import read_raw_fif import easygui_qt.easygui_qt as gui from PyQt5.QtWidgets import QApplication import sys matplotlib.use('Qt5Agg') mne.viz.set_browser_backend('qt') # 初始化QApplication,避免重复创建实例 app = QApplication.instance() or QApplication(sys.argv) fname = sample.data_path() / "MEG" / "sample" / "sample_audvis_raw.fif" raw = read_raw_fif(fname, preload=False, verbose=False) raw.crop(0, 60).pick("eeg") raw.load_data(verbose=False) input1 = gui.get_continue_or_cancel(title="Input 1", message="", continue_button_text="T", cancel_button_text="F") # 以show=False启动浏览器,避免自动触发事件循环 fig = raw.plot(verbose=False, show=False) # 手动显示图形窗口 fig.show() # 弹窗操作,此时事件循环由QApplication管理 input2 = gui.get_continue_or_cancel(title="Input 2", message="", continue_button_text="T", cancel_button_text="F") print(f"In 1: {input1}\t\tIn 2: {input2}") # 保持事件循环运行,直到用户关闭所有Qt窗口 sys.exit(app.exec_())
关键说明
- 统一事件循环:通过
QApplication接管所有Qt组件(MNE浏览器、easygui-qt弹窗)的事件处理,避免多个事件循环冲突。 - 手动控制图形显示:用
show=False启动MNE浏览器,再手动调用fig.show(),防止MNE自行启动临时事件循环。 - 保持脚本运行:最后调用
app.exec_()阻塞脚本,直到用户关闭所有Qt窗口,确保后续代码执行完成。
内容的提问来源于stack exchange,提问作者Jon Nir
相关产品推荐
相关产品推荐

