#------------------------------------------------------------------------------
# Copyright (c) 2012, Enthought, Inc.
# All rights reserved.
#
# Special thanks to Steven Silvester for contributing this module!
#------------------------------------------------------------------------------
from .qt.QtCore import Qt
from .qt.QtGui import QFrame, QVBoxLayout
from .qt_constraints_widget import size_hint_guard
from .qt_control import QtControl
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg
from matplotlib.backends.backend_qt4agg import NavigationToolbar2QTAgg
[docs]class QtMPLCanvas(QtControl):
""" A Qt implementation of an Enaml MPLCanvas.
"""
#: Internal storage for the matplotlib figure.
_figure = None
#: Internal storage for whether or not to show the toolbar.
_toolbar_visible = False
#--------------------------------------------------------------------------
# Setup Methods
#--------------------------------------------------------------------------
[docs] def create_widget(self, parent, tree):
""" Create the underlying widget.
"""
widget = QFrame(parent)
layout = QVBoxLayout()
layout.setContentsMargins(0, 0, 0, 0)
layout.setSpacing(0)
widget.setLayout(layout)
return widget
[docs] def create(self, tree):
""" Create and initialize the underlying widget.
"""
super(QtMPLCanvas, self).create(tree)
self._figure = tree['figure']
self._toolbar_visible = tree['toolbar_visible']
[docs] def init_layout(self):
""" Initialize the layout of the underlying widget.
"""
super(QtMPLCanvas, self).init_layout()
self.refresh_mpl_widget()
#--------------------------------------------------------------------------
# Message Handlers
#--------------------------------------------------------------------------
[docs] def on_action_set_figure(self, content):
""" Handle the 'set_figure' action from the Enaml widget.
"""
self._figure = content['figure']
with size_hint_guard(self):
self.refresh_mpl_widget()
[docs] def on_action_set_toolbar_visible(self, content):
""" Handle the 'set_toolbar_visible' action from the Enaml
widget.
"""
visible = content['toolbar_visible']
self._toolbar_visible = visible
layout = self.widget().layout()
if layout.count() == 2:
with size_hint_guard(self):
toolbar = layout.itemAt(0).widget()
toolbar.setVisible(visible)
#--------------------------------------------------------------------------
# Widget Update Methods
#--------------------------------------------------------------------------
[docs] def refresh_mpl_widget(self):
""" Create the mpl widget and update the underlying control.
"""
# Delete the old widgets in the layout, it's just shenanigans
# to try to reuse the old widgets when the figure changes.
widget = self.widget()
layout = widget.layout()
while layout.count():
layout_item = layout.takeAt(0)
layout_item.widget().deleteLater()
# Create the new figure and toolbar widgets. It seems that key
# events will not be processed without an mpl figure manager.
# However, a figure manager will create a new toplevel window,
# which is certainly not desired in this case. This appears to
# be a limitation of matplotlib. The canvas is manually set to
# visible, or QVBoxLayout will ignore it for size hinting.
figure = self._figure
if figure is not None:
canvas = FigureCanvasQTAgg(figure)
canvas.setParent(widget)
canvas.setFocusPolicy(Qt.ClickFocus)
canvas.setVisible(True)
toolbar = NavigationToolbar2QTAgg(canvas, widget)
toolbar.setVisible(self._toolbar_visible)
layout.addWidget(toolbar)
layout.addWidget(canvas)