Releasing pan function in NavigationToolbar2QT - matplotlib

I want to cancel pan function from other button. So far, my understanding is that when I want to pan&zoom image, I will click 'Pan' button. If I would like to do other function, e.g. 'Mark' function (in my case), I have to click 'Pan' Button again, then click whatever button I want to do.
I have searched for solving this and found something like 'release_pan', 'button_release_event', but I don't understand how to implement them correctly.
To be clear, I want to cancel pan function from 'Mark' button, and here is my code.
import sys
import time
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import Cursor
from matplotlib.backends.qt_compat import QtCore, QtWidgets
if QtCore.qVersion() >= "5.":
from matplotlib.backends.backend_qt5agg import (
FigureCanvas, NavigationToolbar2QT as NavigationToolbar)
else:
from matplotlib.backends.backend_qt4agg import (
FigureCanvas, NavigationToolbar2QT as NavigationToolbar)
from matplotlib.figure import Figure
class ApplicationWindow(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self.coor = [0,0] #temporary user selection
self.cid = None
self._main = QtWidgets.QWidget()
self.setCentralWidget(self._main)
layout = QtWidgets.QVBoxLayout(self._main)
butt = QtWidgets.QHBoxLayout()
self.static_canvas = FigureCanvas(Figure(figsize=(5, 5), dpi=100))
self.addToolBar = NavigationToolbar(self.static_canvas, self)
self.addToolBar.hide()
self.home = QtWidgets.QPushButton('Home')
self.pan = QtWidgets.QPushButton('Pan')
self.mark = QtWidgets.QPushButton('Mark')
butt.addWidget(self.home)
butt.addWidget(self.pan)
butt.addWidget(self.mark)
layout.addLayout(butt)
layout.addWidget(self.static_canvas)
self._static_ax = self.static_canvas.figure.subplots()
self.tar = plt.imread(r'my_image.tif').copy()
self._static_ax.imshow(self.tar)
# Set cursor
self.cursor = Cursor(self._static_ax, horizOn=True, vertOn=True, useblit=True,
color = 'r', linewidth = 1)
#trigger zone
self.home.clicked.connect(self.Home)
self.pan.clicked.connect(self.Pan)
self.mark.clicked.connect(self.Mark)
def coor_onclick(self, event):
"""
This function will get coordination from click and plot it on canvas
"""
#check out-figure click
if event.xdata == None or event.ydata == None:
pass
else:
self.coor[0] = int(event.xdata)
self.coor[1] = int(event.ydata)
# print(self.coor)
#show line marking on canvas
tar = self.tar.copy()
#NOTE:: self.coor = [x,y] = [col, row]
# x = self.coor[0]
# y = self.coor[1]
#marking line
for r in range(tar.shape[1]):
for c in range(tar.shape[0]):
tar[self.coor[1], c] = [255, 0, 0]
tar[r, self.coor[0]] = [255, 0, 0]
#set final mark on canvas
self._static_ax.clear()
self._static_ax.imshow(tar)
self._static_ax.axis('off')
# Set cursor
self.cursor = Cursor(self._static_ax, horizOn=True, vertOn=True, useblit=True,
color = 'r', linewidth = 1)
self.static_canvas.draw()
def Home(self):
self.cid = self.static_canvas.mpl_connect('button_press_event', self.coor_onclick)
self.addToolBar.home()
def Pan(self):
if self.cid is None:
pass
else:
#disconnect to self.coor_onclick
self.static_canvas.mpl_disconnect(self.cid)
self.addToolBar.pan()
def Mark(self):
self.cid = self.static_canvas.mpl_connect('button_press_event', self.coor_onclick)
if __name__ == "__main__":
# Check whether there is already a running QApplication (e.g., if running
# from an IDE).
qapp = QtWidgets.QApplication.instance()
if not qapp:
qapp = QtWidgets.QApplication(sys.argv)
app = ApplicationWindow()
app.show()
app.activateWindow()
app.raise_()
qapp.exec_()
I have modified from matplotlib documentation.

Check the current mode of NavigationToolbar and if the mode is "PAN", set the mode off by calling pan() again (which will uncheck the action (check out the source code for more details.)).
FYI:
You can check the current mode of the NavigationToolbar by using NavigationToolbar.mode.name, currently there are two modes: "ZOOM" and "PAN".
In your code, change function Mark like this:
def Mark(self):
# if the current mode is Pan, set the mode off by unchecking it.
if self.nav_toolbar.mode.name == "PAN":
self.nav_toolbar.pan()
self.cid = self.static_canvas.mpl_connect(
'button_press_event', self.coor_onclick)

Related

PyQt - not showing instance of FigureCanvasQTAgg on QtWidget of TabPane

I'm continuing project described more in that question: PyQt - can't read Excel file
Basically my code looks like this right now:
# This is a sample Python script.
# Press Shift+F10 to execute it or replace it with your code.
# Press Double Shift to search everywhere for classes, files, tool windows, actions, and settings.
import csv
import sys
import numpy as np
from PyQt6 import QtWidgets
from PyQt6.QtWidgets import QDialog, QApplication, QFileDialog, QTableWidget, QTableWidgetItem, QTabWidget, QWidget
from PySide6.QtCore import Slot, SIGNAL
from PyQt6.uic import loadUi
import pandas as pd
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg
from matplotlib.figure import Figure
class MplCanvas(FigureCanvasQTAgg):
def __init__(self, parent=None, width=12, height=5, dpi=100):
fig = Figure(figsize=(width, height), dpi=100)
self.axes = fig.add_subplot(111)
super(MplCanvas, self).__init__(fig)
class MainWindow(QDialog):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent=parent)
self.initUI()
def initUI(self):
loadUi('gui.ui', self)
self.btnShow.setEnabled(False)
self.btnLoad.setEnabled(False)
self.btnBrowse.clicked.connect(self.browseFiles)
self.btnLoad.clicked.connect(self.loadExcelData)
self.btnClean.clicked.connect(self.cleanData)
self.btnShow.clicked.connect(self.showGraphs)
#Slot()
def browseFiles(self):
fname = QFileDialog.getOpenFileName(self, 'Open a file', 'C:\\', "Excel (*.xls *.xlsx)")
self.filename.setText(fname[0])
self.btnLoad.setEnabled(True)
#Slot()
def loadExcelData(self):
column_names = ["Action", "TimeOfFailure", "ReverseRankR", "S(i)", "Cdf", "Ppf", "LogTime"]
df = pd.read_excel(self.filename.text(), "Sheet1", names=column_names)
if df.size == 0:
return
self.tableExcelData.setRowCount(df.shape[0])
self.tableExcelData.setColumnCount(df.shape[1])
self.tableExcelData.setHorizontalHeaderLabels(df.columns)
for row in df.iterrows():
values = row[1]
for col_index, value in enumerate(values):
tableItem = QTableWidgetItem(str(value))
self.tableExcelData.setItem(row[0], col_index, tableItem)
self.btnLoad.setEnabled(False)
self.btnShow.setEnabled(True)
#Slot()
def cleanData(self):
self.btnLoad.setEnabled(True)
self.btnShow.setEnabled(False)
self.tableExcelData.setRowCount(0)
self.tableExcelData.setColumnCount(0)
#Slot()
def showGraphs(self):
timeOfDays = []
cdf = []
ppf = []
logTime = []
for row in range(self.tableExcelData.rowCount()):
isFailure = False
for column in range(self.tableExcelData.columnCount()):
value = self.tableExcelData.item(row, column)
if(column == 0 and str(value.text()) == 'F'):
isFailure = True
if isFailure == True:
if(column == 1): #TimeOfDays
value = int(value.text())
timeOfDays.append(value)
elif(column == 4): #CDF
value = float(value.text())
cdf.append(value)
elif(column == 5):
value = float(value.text())
ppf.append(value)
elif(column == 6):
value = float(value.text())
logTime.append(value)
print(timeOfDays)
print(cdf)
print(ppf)
print(logTime)
#fig = Figure(figsize=(12,5), dpi=100)
#firstSubplot = fig.add_subplot(111)
#firstSubplot.scatter(timeOfDays, ppf, '*')
#firstSubplot.plot(timeOfDays, ppf)
#fig.show()
#plt.plot(timeOfDays, ppf)
#plt.show()
try:
canvasFig = MplCanvas()
canvasFig.axes.scatter(timeOfDays, ppf, s=5, color='red')
canvasFig.axes.plot(timeOfDays, ppf)
canvasFig.draw()
self.tabFirstGraph.setCentralWidget(canvasFig)
except Exception as e:
print('Error: ' + str(e))
#canvas = FigureCanvasTkAgg(fig, master=self)
#canvas.get_tk_widget().pack()
#canvas.draw()
# Press the green button in the gutter to run the script.
if __name__ == '__main__':
app = QApplication(sys.argv)
mainWindow = MainWindow()
mainWidget = QtWidgets.QStackedWidget()
mainWidget.addWidget(mainWindow)
mainWidget.show()
sys.exit(app.exec())
# See PyCharm help at https://www.jetbrains.com/help/pycharm/
I'm trying to generate two graphs (now it's code for only creation of one):
try:
canvasFig = MplCanvas()
canvasFig.axes.scatter(timeOfDays, ppf, s=5, color='red')
canvasFig.axes.plot(timeOfDays, ppf)
canvasFig.draw()
self.tabFirstGraph.setCentralWidget(canvasFig) #
except Exception as e:
print('Error: ' + str(e))
I tried to create another TabPane ("tabFirstGraph" as name of this object) and set canvas figure object to fill this QWidget instance. But I'm getting constantly this error:
Error: 'QWidget' object has no attribute 'setCentralWidget'
I assumed already that problem is with line above (QWidget, QTableWidget don't have this method). But how can I show my canvas figure graph on "First Graph" Tab Pane?
Thanks in advance for your all answers. :)

Qt5 unable to ignore mouse events on Mac OS

I have written a small script that would display the content of a file on the desktop in a transparent window (which is also always on top window). But when I click on some other window, the focus is automatically taken up by the script's window
Below is the script:
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
import sys
import argparse as ap
class Window(QWidget):
def __init__(self, content, width, height):
super().__init__()
self.content = content.strip()
self.swidth = width
self.sheight = height
self.setWindowTitle("Content Display")
self.setWindowOpacity(0.1)
self.setWindowFlags(Qt.WindowTransparentForInput)
self.setWindowFlags(Qt.WindowStaysOnTopHint)
self.setAttribute(Qt.WA_TranslucentBackground, True)
self.setAttribute(Qt.WA_TransparentForMouseEvents)
self.setGeometry(0, 0, self.swidth, self.sheight)
self.text_box = QPlainTextEdit(self)
self.text_box.move(10, 10)
self.tb_width = self.width()
self.tb_height = self.height()
self.text_box.resize(self.tb_width, self.tb_height)
self.content = f"{self.content} " * 1000
self.text_box.setPlainText(self.content)
self.show()
def resizeEvent(self, event):
self.tb_width = self.width()
self.tb_height = self.height()
self.text_box.resize(self.tb_width, self.tb_height)
def keyPressEvent(self, event):
if event.key() == Qt.Key_I:
if event.modifiers() & Qt.ControlModifier:
cur_opacity = self.windowOpacity()
self.setWindowOpacity(cur_opacity + 0.05)
if event.key() == Qt.Key_D:
if event.modifiers() & Qt.ControlModifier:
cur_opacity = self.windowOpacity()
self.setWindowOpacity(cur_opacity - 0.05)
if __name__ == "__main__":
parser = ap.ArgumentParser()
parser.add_argument("-f",
"--file",
required=True,
type=str,
help="File with content")
args = parser.parse_args()
file = args.file
content = ""
try:
fd = open(file, 'r')
content = fd.read()
fd.close()
except:
print("Unable to open the content file")
sys.exit(1)
app = QApplication(sys.argv)
screen = app.primaryScreen()
size = screen.size()
rect = screen.availableGeometry()
window = Window(content, rect.width(), rect.height())
sys.exit(app.exec())
Is there a way in which the focus on the window can be ignored when clicking on another window

How improve this Matplotlib animation?

I have written a program that plots a logarithm gradually. However, there are two issues:
When the animation is completed, and next I minimize the animation window and then maximize it again, the graph is gone.
When I close the animation window while it is still plotting, then the thread myDataLoop continues, and still prints 'done' after some time. The next time I run the program, it will take longer to start the animation, and the animation becomes glitchy. (This continues until I restart the kernel)
How can I solve this?
import numpy as np
import time
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
import matplotlib
matplotlib.use("Qt5Agg")
from matplotlib.figure import Figure
from matplotlib.animation import TimedAnimation
from matplotlib.lines import Line2D
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
import threading
#Time in seconds needed to construct the figure
Time=10
Modified_length=10**9
#We plot a log function
cumulative=[]
for i in range(1,int(Modified_length/8000)+1):
cumulative.append(np.log(i*8000))
class CustomMainWindow(QMainWindow):
def __init__(self):
super(CustomMainWindow, self).__init__()
# Define the geometry of the main window
self.setGeometry(0, 30, 1600, 830)
self.setWindowTitle(" ")
# Create FRAME_A
self.FRAME_A = QFrame(self)
self.FRAME_A.setStyleSheet("QWidget { background-color: %s }" % QColor(210,210,235,255).name())
self.LAYOUT_A = QGridLayout()
self.FRAME_A.setLayout(self.LAYOUT_A)
self.setCentralWidget(self.FRAME_A)
# Place the matplotlib figure
self.myFig = CustomFigCanvas()
self.LAYOUT_A.addWidget(self.myFig, *(0,1))
# Add the callbackfunc to ..
myDataLoop = threading.Thread(name = 'myDataLoop', target = dataSendLoop, daemon = True, args = (self.addData_callbackFunc,))
myDataLoop.start()
self.show()
return
def addData_callbackFunc(self, value):
# print("Add data: " + str(value))
self.myFig.addData(value)
return
''' End Class '''
class CustomFigCanvas(FigureCanvas, TimedAnimation):
def __init__(self):
self.addedData = []
# print(matplotlib.__version__)
# The data
self.xlim = int(Modified_length)
self.n = np.linspace(0, self.xlim - 1, int(self.xlim/8000))
self.y=[0]
# The window
self.fig = Figure(figsize=(5,5), dpi=120)
self.ax1 = self.fig.add_subplot(111)
# self.ax1 settings
self.line1 = Line2D([], [], color='blue')
self.ax1.add_line(self.line1)
self.ax1.set_xlim(0, self.xlim - 1)
self.ax1.set_ylim(0,100)
self.ax2 = self.ax1.twinx()
FigureCanvas.__init__(self, self.fig)
TimedAnimation.__init__(self, self.fig, interval = 50, blit = True)
return
def new_frame_seq(self):
return iter(range(self.n.size))
def _init_draw(self):
lines = [self.line1]
for l in lines:
l.set_data([], [])
return
def addData(self, value):
self.addedData.append(value)
return
def _step(self, *args):
# Extends the _step() method for the TimedAnimation class.
try:
TimedAnimation._step(self, *args)
except Exception:
TimedAnimation._stop(self)
pass
return
def _draw_frame(self, framedata):
global Q
while(len(self.addedData) > 0):
self.y=np.append(self.y,self.addedData[0])
del(self.addedData[0])
l=len(self.y)
self.line1.set_data(self.n[ 0 : l], self.y[ 0 : l ])
self._drawn_artists = [self.line1]
return
''' End Class '''
# You need to setup a signal slot mechanism, to
# send data to your GUI in a thread-safe way.
# Believe me, if you don't do this right, things
# go very very wrong..
class Communicate(QObject):
data_signal = pyqtSignal(float)
''' End Class '''
def dataSendLoop(addData_callbackFunc):
# Setup the signal-slot mechanism.
mySrc = Communicate()
mySrc.data_signal.connect(addData_callbackFunc)
# Use the log data
# n = np.linspace(0, int(Modified_length)-1, int(Modified_length))
totaly=cumulative
i = 0
while(True):
if(i > int(Modified_length/8000)-1):
print('done')
break
i = 0
time.sleep(100*Time/Modified_length)
for j in range(100):
mySrc.data_signal.emit(totaly[i]) # <- Here you emit a signal!
i += 1
###
###
if __name__== '__main__':
app = QApplication(sys.argv)
QApplication.setStyle(QStyleFactory.create('Plastique'))
myGUI = CustomMainWindow()
sys.exit(app.exec_())

Is it possible to recreate a pyqtgraph without data

I have a pyqt5 based application where I open a file and plot 2 different plots based on the data from the file. Now I want to open another similar file, but I want to save the status/view of the 2 plots, so that I could come quickly back to the previous plots/views, without having to plot it again by reading the data. Is it possible at all to save the state/view of the plots to recreate it very quickly?
You can guide from this answer .
Basically, you can use the PlotWidget class from pyqtgraph.
Generate a PlotWidget.
import pyqtgraph as pg
plot_widget = pg.PlotWidget()
Use the plot() method and store the PlotDataItem in a variable. The PlotDataItem will contain the information of that specific plot: x-data, y-data, the color of the line, the line width, ...
plot_item = plot_widget.plot(xData, yData)
With this you can add/remove the item from the plot every time you want with the addItem() and removeItem() methods
plot_widget.removeItem(plot_item)
plot_widget.addItem(plot_item)
EDIT:
To get the view state of the plot, you can use the viewRect() method of the PlotWidget class. It will return a QRectF object which contains the information of the view state like this:
PyQt5.QtCore.QRectF(x_0, y_0, w, h)
Where:
x_0 and y_0 are the coordinates where the view starts.
w and h are the width and height of the view area.
Also, you can restore the view using the setRange() method of the PlotWidget class.
Example:
Here is an example of the implementation of this:
import sys
import numpy as np
import pyqtgraph as pg
from pyqtgraph.Qt import QtGui
class MyApp(QtGui.QWidget):
def __init__(self):
QtGui.QWidget.__init__(self)
self.central_layout = QtGui.QVBoxLayout()
self.buttons_layout = QtGui.QVBoxLayout()
self.boxes_layout = QtGui.QHBoxLayout()
self.save = QtGui.QPushButton('Save View')
self.set = QtGui.QPushButton('Set View')
self.boxes = [QtGui.QCheckBox(f"Box {i+1}") for i in range(3)]
self.plot_widget = pg.PlotWidget()
self.plot_data = [None for _ in range(3)]
self.state = [False for _ in range(3)]
self.setLayout(self.central_layout)
self.central_layout.addWidget(self.plot_widget)
self.central_layout.addLayout(self.buttons_layout)
self.buttons_layout.addLayout(self.boxes_layout)
self.buttons_layout.addWidget(self.save)
self.buttons_layout.addWidget(self.set)
for i in range(3):
self.boxes_layout.addWidget(self.boxes[i])
self.boxes[i].stateChanged.connect(self.box_changed)
self.create_data()
self.save.clicked.connect(self.save_view)
self.set.clicked.connect(self.set_view)
self.view_state = None
self.save_view()
def create_data(self):
x = np.linspace(0, 3.14, 100)
y = [np.sin(x), np.cos(x), np.sin(x)**2]
for i in range(3):
self.plot_data[i] = pg.PlotDataItem(x, y[i])
def box_changed(self):
for i in range(3):
if self.boxes[i].isChecked() != self.state[i]:
self.state[i] = self.boxes[i].isChecked()
if self.state[i]:
if self.plot_data[i] is not None:
self.plot_widget.addItem(self.plot_data[i])
else:
self.plot_data[i] = self.plot_widget.plot(*self.box_data[i])
else:
self.plot_widget.removeItem(self.plot_data[i])
break
def save_view(self):
self.view_state = self.plot_widget.viewRect()
def set_view(self):
self.plot_widget.setRange(self.view_state)
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
window = MyApp()
window.show()
sys.exit(app.exec_())

Colorbar disappear during animation of image when changing colormap

I created a subplot in a figure for displaying an image with imshow, and I add a colorbar. With no animation, I can change the colormap changing the value of the ComboBox and the colorbar is updated correctly.
But if I add an animation, the colorbar disappear each time I change the colormap. I have to click on another window (other software, etc) or resize the GUI to see the colorbar again.
Here is an example to understand the problem :
import sys
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
import matplotlib
matplotlib.use('Qt5Agg')
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import make_axes_locatable
from matplotlib import animation
class FenetrePrincipale(QWidget):
def __init__(self, parent=None):
super(FenetrePrincipale, self).__init__(parent)
self.setupUi(self)
# Fonction de configuration de la classe
def setupUi(self, Form):
self.Form = Form
Form.setMinimumSize(1220, 850)
self.creation_GUI()
self.creation_figure()
self.creation_layout()
self.tabWidget.setCurrentIndex(0)
self.Bouton_quitter.clicked.connect(self.close)
self.anim = animation.FuncAnimation(self.figure, self.animate, interval=10, blit=True)
self.Widget_choixPalette_ComboBox.currentIndexChanged.connect(self.changementPalette)
def changementPalette(self, onglet):
self.image.set_cmap('binary')
self.canvas.draw()
def animate(self, i):
# a = self.thread_1.img
self.image.set_array(self.imageInit)
return [self.image]
def resizeEvent(self, QResizeEvent):
self.tabWidget.setMinimumSize(QSize(self.width() - 20, self.height() - 60))
def creation_GUI(self):
self.tabWidget = QTabWidget()
self.tab1 = QWidget()
self.tabWidget.addTab(self.tab1, " Tab1 ")
self.Widget_choixPalette_Label = QLabel(self.tab1)
self.Widget_choixPalette_Label.setText("Text1")
self.Widget_choixPalette_ComboBox = QComboBox(self.tab1)
self.Widget_choixPalette_ComboBox.addItem("Try1")
self.Widget_choixPalette_ComboBox.addItem("Try2")
self.Bouton_quitter = QPushButton(self.tab1)
self.Bouton_quitter.setText("Quit")
def creation_layout(self):
LayoutForm = QGridLayout(self)
LayoutForm.addWidget(self.tabWidget, 0, 0, 1, 1)
LayoutTab1 = QGridLayout(self.tab1)
LayoutTab1.addWidget(self.Widget_choixPalette_Label, 0, 1, 1, 1)
LayoutTab1.addWidget(self.Widget_choixPalette_ComboBox, 1, 1, 1, 1)
self.Widget_choixPalette_ComboBox.setMinimumWidth(200)
LayoutTab1.addWidget(self.canvas, 2, 0, 1, 3)
LayoutTab1.addWidget(self.Bouton_quitter, 2, 3, 1, 1, Qt.AlignRight | Qt.AlignBottom)
LayoutTab1.setRowStretch(2, 1)
LayoutTab1.setColumnStretch(0, 1)
LayoutTab1.setColumnStretch(2, 1)
def creation_figure(self):
# Create figure (transparent background)
self.figure = plt.figure()
# self.figure.patch.set_facecolor('None')
self.canvas = FigureCanvas(self.figure)
self.canvas.setStyleSheet("background-color:transparent;")
# Adding one subplot for image
self.axe0 = self.figure.add_subplot(111)
self.axe0.get_xaxis().set_visible(False)
self.axe0.get_yaxis().set_visible(False)
# Data for init image
self.imageInit = [[255] * 320 for i in range(240)]
self.imageInit[0][0] = 0
# Init image and add colorbar
self.image = self.axe0.imshow(self.imageInit, interpolation='none')
divider = make_axes_locatable(self.axe0)
cax = divider.new_vertical(size="5%", pad=0.05, pack_start=True)
self.colorbar = self.figure.add_axes(cax)
self.figure.colorbar(self.image, cax=cax, orientation='horizontal')
plt.subplots_adjust(left=0, bottom=0.05, right=1, top=1, wspace=0, hspace=0)
self.canvas.draw()
if __name__ == '__main__':
app = QApplication(sys.argv)
# QApplication.setStyle(QStyleFactory.create("plastique"))
form = FenetrePrincipale()
form.show()
sys.exit(app.exec_())
When I change of colormap selecting any choice in combobox :
What I am waiting to see :
Operating system: Windows 7 Pro
Matplotlib version: 2.1.0
Matplotlib backend: Qt5Agg
Python version: 3.6
a] blit=False
Use blit=False in the animation. Otherwise only the image itself will be updated and the redrawing of the complete canvas is posponed to some event that makes this redrawing necessary, e.g. a resize event.
b] pause animation
In case you cannot affort using blit=False, you can pause the animation, change the colormap, draw the canvas, then continue the animation.
def changementPalette(self, onglet):
self.anim.event_source.stop()
if onglet==0:
self.image.set_cmap('viridis')
else:
self.image.set_cmap('binary')
self.canvas.draw_idle()
self.anim.event_source.start()