0

I'm embedding a matplotlib figure in PyQt4 UI. Something like

Building a matplotlib GUI with Qt Designer.

FigureCanvasQTAgg and NavigationToolbar2QT are added in QVBoxlayout and right side of UI is a QListWidget of figure names.

None of the toolbar shortcuts are working. I tried changing focus of the both QVBoxlayout and QListWidget Widget.

Figure is generated as

from matplotlib.figure import Figure
fig=figure()
ax=fig.add_subplot(111)
ax.plot.plot(np.random.rand(5))

This figure is passed to addmpl method where canvas and toolbar are generated and added to the mainwindow widget.

def addmpl(self,fig):
    self.canvas = FigureCanvas(fig)
    self.mplvl.addWidget(self.canvas)
    self.canvas.draw()
    self.toolbar = NavigationToolbar(self.canvas,self.mplwindow)
    self.mplvl.addWidget(self.toolbar)

Workaround...

def menu(self):
    self.savefig=QtGui.QAction('&Save', self) 
    self.savefig.setShortcut('Ctrl+S')
    self.savefig.triggered.connect(self.save_figure)

    undo=QtGui.QAction('&Undo', self)
    undo.setShortcut('Ctrl+Z')
    undo.triggered.connect(self.back)

    redo=QtGui.QAction('&Redo', self)
    redo.setShortcut('Ctrl+Y')
    redo.triggered.connect(self.forward)

    figoptions=QtGui.QAction('&Figure Options', self)
    figoptions.setShortcut('Ctrl+F')
    figoptions.setStatusTip('Edit curves lines and axes parameters')
    figoptions.triggered.connect(self.edit_parameters)



def back(self):
    self.toolbar.back()
def forward(self):
    self.toolbar.forward()
def save_figure(self):
    self.toolbar.save_figure()
def edit_parameters(self):
    self.toolbar.edit_parameters()

But the shortcuts like Constrain pan/zoom to x axis - hold x when panning/zooming with mouse looks difficult and tedious to implement.

Solution of this Question has the same problem.(Replaced NavigationToolbar2QTAgg with NavigationToolbar2QT)

5
  • Are the slots called? Ie if you put print statements in back() forward() etc do you get anything in console from which GUI started? If not then the issue is likely related to how toolbar is integrated rather that the actual qactions, in that case you need to post related code. Commented Dec 28, 2016 at 22:23
  • I have put 'print("Hello")' in pan method of backend_bases.py. On pressing p (shortcut for pan) console remains empty. But if I click pan button in toolbar, console prints Hello. Commented Dec 29, 2016 at 8:45
  • Example code is available here Commented Dec 29, 2016 at 8:49
  • So you mean it's the keyboard shortcuts of the toolbar buttons that don't work, but the button actions actually work (if you click on them)? Commented Dec 29, 2016 at 12:55
  • Yes... Only Keyboard shortcuts don't work... Commented Dec 29, 2016 at 14:16

2 Answers 2

4

Without seeing the portion of your code where you intialize the figure, and after looking at the PyQt example, I'm taking a wild guess that you haven't configure keyboard shortcuts:

  1. Ensure you have from matplotlib.backend_bases import key_press_handler
  2. Bind the matplotlib figure canvas's keypresses to a handler:

    self.fig = Figure(...)
    self.canvas = FigureCanvas(self.fig)
    self.mpl_nav_toolbar = NavigationToolbar(...)
    ...
    self.canvas.mpl_connect('key_press_event', self.on_key_press)
    
  3. Configure the canvas widget to process keyboard events:

    ...
    self.canvas.setFocusPolicy(Qt.StrongFocus)
    
  4. Define your handler to call key_press_handler:

    def on_key_press(self, event):
        key_press_handler(event, self.canvas, self.mpl_nav_toolbar)
    

These steps should work for PyQt5 as well, BTW.

Sign up to request clarification or add additional context in comments.

4 Comments

Maybe this is mistake about focus....because when i click 'T' button the selection in figure list changes to 'Two Plot'....
Tried this...but it didn't work....updated code is available here....UI file is available here.....
Adding self.canvas.setFocusPolicy(Qt.StrongFocus) and self.canvas.setFocus() solved the problem.... Thanks for pointing me in the right direction.....
Ah thx forgot about the focus policy, which defaults to none, so I updated answer. However, I doubt the setFocus() is required: with StrongFocus, you should be able to just tab to or click on the canvas or toolbar to have canvas get focus. Let me know if there is more I can improve to the answer for upvote.
0

This is an alternative solution which is PyQt specific (tested with PyQt5). It is not as concise as mpl_connect('key_press_event'...) but allows for more flexibility such as redefining the shortcut keys.

NavigationToolbar2QT inherits from QToolBar which in turn inherits from QWidget. All the actions on the toolbar are therefore available through QWidget.actions().

For example, a global shortcut can be defined and connected to zoom on toolbar:

class Main(QMainWindow, Ui_MainWindow):
    def __init__(self, ):
        ...        
        self.shortcut = QShortcut(QKeySequence(Qt.Key_Z), self)
        ....

    def addmpl(self, fig):
        ...
        for action in self.toolbar.actions():
            if action.text() == 'Zoom':
                self.shortcut.activated.connect(action.trigger)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.