10000 bring osx backend flush_events to feature parity with other backend · Issue #17642 · matplotlib/matplotlib · GitHub
[go: up one dir, main page]

Skip to content
bring osx backend flush_events to feature parity with other backend #17642
Closed
@tacaswell

Description

@tacaswell

Bug report

While reviewing #10187 it was noted the cv.flush_events does not work the same with the osx backend as the other GUI backends.

I suspect that if someone knows how to work with the OSX GUI code this will be straight forward to implement.

Bug summary

The issue is likely the flush_events function in the objective-c code does not appear to process any of the pending UI events

matplotlib/src/_macosx.m

Lines 391 to 402 in 77f23da

static PyObject*
FigureCanvas_flush_events(FigureCanvas* self)
{
View* view = self->view;
if(!view)
{
PyErr_SetString(PyExc_RuntimeError, "NSView* is NULL");
return NULL;
}
[view displayIfNeeded];
Py_RETURN_NONE;
}

The

Code for reproduction

Run the exampls in #10187

import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(0, 2 * np.pi, 100)

fig, ax = plt.subplots()

# animated=True tells matplotlib to only draw the artist when we
# explicitly request it
(ln,) = ax.plot(x, np.sin(x), animated=True)

# make sure the window is raised, but the script keeps going
plt.show(block=False)

# stop to admire our empty window axes and ensure it is rendered at
# least once.
#
# We need to fully draw the figure at its final size on the screen
# before we continue on so that :
#  a) we have the correctly sized and drawn background to grab
#  b) we have a cached renderer so that ``ax.draw_artist`` works
# so we spin the event loop to let the backend process any pending operations
plt.pause(0.1)

# get copy of entire figure (everything inside fig.bbox) sans animated artist
bg = fig.canvas.copy_from_bbox(fig.bbox)
# draw the animated artist, this uses a cached renderer
ax.draw_artist(ln)
# show the result to the screen, this pushes the updated RGBA buffer from the
# renderer to the GUI framework so you can see it
fig.canvas.blit(fig.bbox)

for j in range(100):
    # reset the background back in the canvas state, screen unchanged
    fig.canvas.restore_region(bg)
    # update the artist, neither the canvas state nor the screen have changed
    ln.set_ydata(np.sin(x + (j / 100) * np.pi))
    # re-render the artist, updating the canvas state, but not the screen
    ax.draw_artist(ln)
    # copy the image to the GUI state, but screen might not changed yet
    fig.canvas.blit(fig.bbox)
    # flush any pending GUI events, re-painting the screen if needed
    fig.canvas.flush_events()
    # you can put a pause in if you want to slow things down
    # plt.pause(.1)

Actual outcome

The window does not update during the loop

Expected outcome

It behaves as when plt.pause(.1) is un-commented

Matplotlib version

  • Operating system: OSX
  • Matplotlib version: 3.2+
  • Matplotlib backend (print(matplotlib.get_backend())): OSX
  • Python version: ?

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      0