1

I have a pyQt application with several embedded matplotlib widgets (https://github.com/chipmuenk/pyFDA).

The automatic updating of plots can be turned off for each plotting widget to speed up the application (especially 3D plots can take quite long).

Unfortunately, I haven't managed to disable (grey out) the canvas completely yet. What I'd like is to do something like

class MplWidget(QWidget):
    """
    Construct a subwidget with Matplotlib canvas and NavigationToolbar
    """

    def __init__(self, parent):
        super(MplWidget, self).__init__(parent)
        # Create the mpl figure and construct the canvas with the figure
        self.fig = Figure()
        self.pltCanv = FigureCanvas(self.fig)
#-------------------------------------------------

self.mplwidget = MplWidget(self)
self.mplwidget.pltCanv.setEnabled(False) # <- this doesn't work

to make it clear that there is nothing to interact with in this widget. Is there an easy workaround?

5
  • 1
    Is this about changing the color to grey or about preventing any user interaction? Commented Nov 17, 2017 at 11:29
  • Preventing any user interaction would be better but "greying out" would be sufficient. But I haven't even managed to do that ... Commented Nov 17, 2017 at 13:41
  • Greying: Use a patch as large as the figure, set its zorder very high, make it semitransparent. Preventing user interaction: disconnect all events from the canvas (this is a matplotlib operation, not one of PyQt). (I guess I could provide an answer, but in case of the second option it would be necessary to have a minimal reproducible example available for testing.) Commented Nov 17, 2017 at 14:19
  • No thanks, using a patch is fine for me - the other option sounds too complicated for a small UI improvement. As a third alternative, I'm clearing the figure (clf()) - not too pretty, but it also does the job. If you repost the patch solution as an answer, I could give you a credit. Commented Nov 17, 2017 at 14:27
  • Although I'm aware this question has a different (visual) context - since it contains "Disable matplotlib widget": there is also a matplotlib.widgets.Widget.set_active(active), which probably corresponds to disabling a widget. Note, though, that set_active for Radio and CheckButtons has different meaning! Commented Jan 27, 2022 at 22:58

1 Answer 1

2

Grey out figure.

You may grey out the figure by placing a grey, semitransparent patch on top of it. To this end, you may create a Rectangle, set its zorder very high and give it the figure transform. To add it to a an axes, you may use ax.add_patch; however in order to add it to a figure with a 3D axes, this will not work and you would need to add it via fig.patches.extend. (See this answer)

import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.plot([1,3,2],[1,2,3],[2,3,2])

rect=plt.Rectangle((0,0),1,1, transform=fig.transFigure, 
                   clip_on=False, zorder=100, alpha=0.5, color="grey")
fig.patches.extend([rect])

plt.show()

enter image description here

Disconnecting all events

You may disconnect all events from the canvas. This will prevent any user interaction, but is also not reversible; so if you need those events back at a later stage the solution would be more complicated.

import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.plot([1,3,2],[1,2,3],[2,3,2])

for evt, callback in fig.canvas.callbacks.callbacks.items():
    for cid, _ in callback.items():
        fig.canvas.mpl_disconnect(cid)
plt.show()
Sign up to request clarification or add additional context in comments.

1 Comment

Thanx for extending your answer to 3D axes as well (which I do need)!

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.