Создание подкласса matplotlib NavigationToolbar выдает ошибку с панорамированием / масштабированием

Я разрабатываю инструмент для разработки и анализа фильтров на основе графического интерфейса ( 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. ... функции "панорамирование / масштабирование" и "прямоугольник масштабирования" выдают следующую ошибку (но, тем не менее, масштабирование и панорамирование). Traceback (последний вызов был последним):

    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 не работают, и также нет визуальной подсказки, выбрана ли функция или нет. Должен признать, я не совсем понимаю интерфейс (QAction?) Для комбинированных функций pan/zoom - я еще не очень опытный Pythonista.

  2. ... моя новая функция "полный просмотр масштаба" работает, но настройку масштабирования нельзя отменить с помощью "предыдущего / следующего просмотра". Это не вызывает большого удивления, так как я не добавляю настройки вида в список (?) Настроек вида, не зная, с чего начать:-)

Кто может быть так любезен, чтобы дать мне небольшой старт, как правильно применить панель навигации?

И (бесстыдная заглушка:-)): Кто-нибудь хочет внести свой вклад в проект? Следующими шагами будет 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 ответ

Решение

Выполнение некоторого реверс-инжиниринга с оригинальным 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 и Qt: нажатие мышью event.key всегда None

Проблема в том, что события нажатия клавиш в целом не обрабатываются, если вы "не активируете фокус qt на холсте mpl". Решение состоит в том, чтобы добавить две строки в класс MplWidget:

self.canvas.setFocusPolicy( QtCore.Qt.ClickFocus )
self.canvas.setFocus()
Другие вопросы по тегам