子类化matplotlib NavigationToolbar会引发平移/缩放错误

时间:2015-03-25 13:18:41

标签: python qt matplotlib pyqt qaction

我正在开发基于GUI的过滤器设计和分析工具(https://github.com/chipmuenk/pyFDA),继承matplotlib NavigationToolbar以实现一些更改(添加/删除的功能和按钮,新的图标集)。完整代码位于https://github.com/chipmuenk/pyFDA/下。每个(标签式)plot_ *小部件实例化子类化NavigationToolbar的副本,例如,来自plot_widgets / plot_phi.py:

from plot_widgets.plot_utils import MplWidget
class PlotPhi(QtGui.QMainWindow):

    def __init__(self, parent = None, DEBUG = False): # default parent = None -> top Window
        super(PlotPhi, self).__init__(parent)
        self.mplwidget = MplWidget()
        self.mplwidget.setFocus()
        self.setCentralWidget(self.mplwidget)

        ax = self.mplwidget.fig.add_subplot(111)

总的来说,这很有效但是......

  1. ...功能“平移/缩放”和“缩放矩形”会引发以下错误(但仍然可以缩放和平移)。     回溯(最近一次调用最后一次):

    File "D:\Programme\WinPython-64bit-3.4.3.1\python-3.4.3.amd64\lib\site-
      packages\matplotlib\backends\backend_qt5.py", 
    
    line 666, in zoom
        self._update_buttons_checked()
    File "D:\Programme\WinPython-64bit-3.4.3.1\python-3.4.3.amd64\lib\site-
      packages\matplotlib\backends\backend_qt5.py", 
    
    line 657, in _update_buttons_checked
        self._actions['pan'].setChecked(self._active == 'PAN')
    KeyError: 'pan'
    

    鼠标修饰符x和y不起作用,也没有视觉提示是否选择了该功能。我必须承认,我不太了解组合功能pan / zoom的界面(QAction?) - 我还不是一个经验丰富的Pythonista。

  2. ...我的新功能“缩放全视图”有效,但使用“上一个/下一个视图”无法撤消缩放设置。这并不是什么大惊喜,因为我没有将视图设置添加到视图设置列表(?),不知道从哪里开始: - )

  3. 对于如何正确应用导航工具栏,谁可以如此友善?

    (无耻的插件:-)):任何有志于为该项目做出贡献的人?接下来的步骤将是VHDL / Verilog - 使用myHDL导出(http://myhdl.org)并保存/加载过滤器功能

    这是plot_widgets / plot_utils.py

    的剪裁片段
    from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
    from matplotlib.backends.backend_qt4agg import NavigationToolbar2QT as NavigationToolbar
    from matplotlib.backend_bases import cursors as mplCursors
    from matplotlib.figure import Figure
    
    class MyMplToolbar(NavigationToolbar):
        """
        Custom Matplotlib Navigationtoolbar, subclassed from
        NavigationToolbar.
    
        derived from http://www.python-forum.de/viewtopic.php?f=24&t=26437
        """
    
        def _init_toolbar(self):
    #        self.basedir = os.path.join(rcParams[ 'datapath' ], 'images/icons')
            iconDir = os.path.join(os.path.dirname(os.path.abspath(__file__)),
               '..','images','icons', '')
        # HOME:
        a = self.addAction(QtGui.QIcon(iconDir + 'home.svg'), \
                           'Home', self.home)
        a.setToolTip('Reset original view')
        # BACK:
        a = self.addAction(QtGui.QIcon(iconDir + 'action-undo.svg'), \
                           'Back', self.back)
        a.setToolTip('Back to previous view')
    
        # PAN:
        a = self.addAction(QtGui.QIcon(iconDir + 'move.svg'), \
                           'Pan', self.pan)
    #                           'Pan', self.pan('self.move','self.pan')) # nearly works ...
        a.setToolTip('Pan axes with left mouse button, zoom with right')
        # ZOOM RECTANGLE:
        a = self.addAction(QtGui.QIcon(iconDir + 'magnifying-glass.svg'), \
                           'Zoom', self.zoom)
        a.setToolTip('Zoom in / out to rectangle with left / right mouse button.')
        # Full View:
        a = self.addAction(QtGui.QIcon(iconDir + 'fullscreen-enter.svg'), \
            'Full View', self.parent.pltFullView)
        a.setToolTip('Full view')
        self.buttons = {}
    
        # reference holder for subplots_adjust window
        self.adj_window = None
    

1 个答案:

答案 0 :(得分:0)

使用原始NavigationToolbar进行一些逆向工程显示了一些缺失的部分:

# PAN:
self.a_pa = self.addAction(QtGui.QIcon(iconDir + 'move.svg'), \
                       'Pan', self.pan)
self.a_pa.setToolTip('Pan axes with left mouse button, zoom with right')
self._actions['pan'] = self.a_pa
self.a_pa.setCheckable(True)

self.a_pa.setEnabled(True) # enable / disable function programwise

上面的代码消除了错误并给出了视觉提示(" setCheckable")是否选择了Pan。

"完整视图"可以通过调用

轻松添加到视图限制历史记录中
self.myNavigationToolbar.push_current()
在更改视图之前

(例如通过自动缩放)。

缺少鼠标修饰符的解决方案同样简单(当你知道如何,那就是......)如SO帖子所示

matplotlib and Qt: mouse press event.key is always None

  

问题在于,除非您将qt的焦点激活到mpl画布上,否则不会处理关键的新闻事件。解决方案是在MplWidget类中添加两行:

self.canvas.setFocusPolicy( QtCore.Qt.ClickFocus )
self.canvas.setFocus()