Hi, recently I was trying to embed the interactive figure gotten from mne.viz.plot_raw in a PyQt5 GUI, which I have asked before, but it became non-interactive. I tried to embed an interactive matplotlib.figure.Figure instance to do the same thing and it worked. Here is the code:
import matplotlib
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar
# from matplotlib.backends.qt_compat import QtCore
from PyQt5 import QtCore
from matplotlib.figure import Figure
from PyQt5 import QtWidgets
import sys
import numpy as np
class My_Main_window(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(My_Main_window, self).__init__(parent)
self.canvas = FigureCanvas(Figure(constrained_layout=True))
self.canvas.draw()
self.ax = self.canvas.figure.add_subplot()
self.con_1 = np.random.random((30, 40, 10))
self.num = 0
con_plot = self.con_1[:, :, self.num]
self.im = self.ax.matshow(con_plot)
self.ax.set_title(self.num)
self.canvas.figure.colorbar(self.im)
self.canvas.mpl_connect('key_press_event', self.on_move)
self.canvas.mpl_connect(
"button_press_event", lambda *args, **kwargs: print(args, kwargs)
)
self.canvas.mpl_connect(
"key_press_event", lambda *args, **kwargs: print(args, kwargs)
)
self.setCentralWidget(self.canvas)
# Give the keyboard focus to the figure instead of the manager:
# StrongFocus accepts both tab and click to focus and will enable the
# canvas to process event without clicking.
# https://doc.qt.io/qt-5/qt.html#FocusPolicy-enum
self.canvas.setFocusPolicy(QtCore.Qt.StrongFocus)
self.canvas.setFocus()
print(type(self.canvas))
def on_move(self, event):
print(f"activate this {event.key}, {self.num}")
if event.key == "left":
if self.num == 0:
self.num = 0
con_plot = self.con_1[:, :, self.num]
else:
self.num -= 1
con_plot = self.con_1[:, :, self.num]
elif event.key == "right":
if self.num == self.con_1.shape[2] - 1:
self.num = 0
con_plot = self.con_1[:, :, self.num]
else:
self.num += 1
con_plot = self.con_1[:, :, self.num]
else:
con_plot = self.con_1[:, :, self.num]
# update the image in place
self.im.set_data(con_plot)
self.ax.set_title(self.num)
# tell Qt that the widget needs to be re-repainted
self.canvas.draw_idle()
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
app.setApplicationName("Plot")
main_win = My_Main_window()
main_win.show()
app.exec()import matplotlib
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar
# from matplotlib.backends.qt_compat import QtCore
from PyQt5 import QtCore
from matplotlib.figure import Figure
from PyQt5 import QtWidgets
import sys
import numpy as np
class My_Main_window(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(My_Main_window, self).__init__(parent)
self.canvas = FigureCanvas(Figure(constrained_layout=True))
self.canvas.draw()
self.ax = self.canvas.figure.add_subplot()
self.con_1 = np.random.random((30, 40, 10))
self.num = 0
con_plot = self.con_1[:, :, self.num]
self.im = self.ax.matshow(con_plot)
self.ax.set_title(self.num)
self.canvas.figure.colorbar(self.im)
self.canvas.mpl_connect('key_press_event', self.on_move)
self.canvas.mpl_connect(
"button_press_event", lambda *args, **kwargs: print(args, kwargs)
)
self.canvas.mpl_connect(
"key_press_event", lambda *args, **kwargs: print(args, kwargs)
)
self.setCentralWidget(self.canvas)
# Give the keyboard focus to the figure instead of the manager:
# StrongFocus accepts both tab and click to focus and will enable the
# canvas to process event without clicking.
# https://doc.qt.io/qt-5/qt.html#FocusPolicy-enum
self.canvas.setFocusPolicy(QtCore.Qt.StrongFocus)
self.canvas.setFocus()
print(type(self.canvas))
def on_move(self, event):
print(f"activate this {event.key}, {self.num}")
if event.key == "left":
if self.num == 0:
self.num = 0
con_plot = self.con_1[:, :, self.num]
else:
self.num -= 1
con_plot = self.con_1[:, :, self.num]
elif event.key == "right":
if self.num == self.con_1.shape[2] - 1:
self.num = 0
con_plot = self.con_1[:, :, self.num]
else:
self.num += 1
con_plot = self.con_1[:, :, self.num]
else:
con_plot = self.con_1[:, :, self.num]
# update the image in place
self.im.set_data(con_plot)
self.ax.set_title(self.num)
# tell Qt that the widget needs to be re-repainted
self.canvas.draw_idle()
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
app.setApplicationName("Plot")
main_win = My_Main_window()
main_win.show()
app.exec()
This codes is to change different figures using the keyboard. These two lines of codes are the key to implement this:
self.canvas.setFocusPolicy(QtCore.Qt.StrongFocus)
self.canvas.setFocus()
So I did this:
import matplotlib
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.qt_compat import QtCore
from PyQt5 import QtWidgets
import sys
from mne.datasets import sample
import mne
class My_Main_window(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(My_Main_window, self).__init__(parent)
data_path = sample.data_path()
fpath= data_path + '/MEG/sample/sample_audvis_raw.fif'
self.data = mne.read_epochs(fpath, preload=True)
self.fig = mne.viz.plot_epochs(self.data, title='1', show=False)
self.canvas = FigureCanvas(self.fig)
self.canvas.draw()
self.stack = QtWidgets.QStackedWidget()
self.stack.addWidget(self.canvas)
self.setCentralWidget(self.stack)
# Give the keyboard focus to the figure instead of the manager:
# StrongFocus accepts both tab and click to focus and will enable the
# canvas to process event without clicking.
# https://doc.qt.io/qt-5/qt.html#FocusPolicy-enum
self.canvas.setFocusPolicy(QtCore.Qt.StrongFocus | QtCore.Qt.WheelFocus)
self.canvas.setFocus()
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
app.setApplicationName("Plot")
main_win = My_Main_window()
main_win.show()
app.exec()
While it is still non-interactive, which bothers me now.