如何通过自定义Mark按钮取消NavigationToolbar2QT的pan平移功能
解决方法
你只需要修改Mark方法,加入pan模式的判断和退出逻辑即可,同时顺便修复原代码多次点击Mark会重复绑定点击事件的问题:
核心修改点
NavigationToolbar2QT的pan()方法是切换逻辑:第一次调用激活平移,第二次调用就会退出平移。工具栏的_active属性会存储当前激活的功能状态,当pan模式激活时该属性值为PAN,我们判断到该状态时主动调用一次pan()即可自动退出平移模式。
修改后的Mark方法如下:
def Mark(self): # 先断开已有绑定,避免重复触发标记逻辑 if self.cid is not None: self.static_canvas.mpl_disconnect(self.cid) # 自动退出pan平移模式 if self.addToolBar._active == 'PAN': self.addToolBar.pan() # 绑定标记功能的点击事件 self.cid = self.static_canvas.mpl_connect('button_press_event', self.coor_onclick)
完整可运行代码
import sys 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 = np.random.randint(0,255,(200,200,3), dtype=np.uint8) # 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) #show line marking on canvas tar = self.tar.copy() #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): if self.cid is not None: self.static_canvas.mpl_disconnect(self.cid) self.cid = self.static_canvas.mpl_connect('button_press_event', self.coor_onclick) self.addToolBar.home() def Pan(self): if self.cid is not None: #disconnect to self.coor_onclick self.static_canvas.mpl_disconnect(self.cid) self.cid = None self.addToolBar.pan() def Mark(self): # 先断开已有绑定,避免重复触发标记逻辑 if self.cid is not None: self.static_canvas.mpl_disconnect(self.cid) # 自动退出pan平移模式 if self.addToolBar._active == 'PAN': self.addToolBar.pan() # 绑定标记功能的点击事件 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_()
内容的提问来源于stack exchange,提问作者CHAVISA SORNSAKUL
相关产品推荐
相关产品推荐

