Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature request: pre_draw_event #5042

Closed
astrofrog opened this issue Sep 9, 2015 · 8 comments
Closed

Feature request: pre_draw_event #5042

astrofrog opened this issue Sep 9, 2015 · 8 comments
Milestone

Comments

@astrofrog
Copy link
Contributor

At the moment draw_event is triggered after a draw, but it would be great to be able to specify callbacks that happen just before the drawing is done. Is this something that would be easy to implement? (e.g. as pre_draw_event, and maybe rename draw_event to post_draw_event with a backward-compatible alias?)

@tacaswell tacaswell added this to the proposed next point release milestone Sep 9, 2015
@tacaswell
Copy link
Member

Why?

@WeatherGod
Copy link
Member

Why not?
On Sep 9, 2015 6:38 PM, "Thomas A Caswell" notifications@github.com wrote:

Why?


Reply to this email directly or view it on GitHub
#5042 (comment)
.

@mdehoon
Copy link
Contributor

mdehoon commented Sep 10, 2015

Why not?

To avoid API bloat.

@astrofrog
Copy link
Contributor Author

Just to clarify my use case - this came about because I was working on finding a way to update the position of the axes before each draw event (see my emails on the mailing list yesterday). The solution I came up with looks something like this:

https://gist.github.com/astrofrog/8d579ea83e578a9cdb99

where I basically have to subclass the axes class. However, I wanted to find a way to do this that would not require subclassing axes, because I want it to be applicable to various existing Axes subclasses, and don't want to have to subclass each of them. So the natural solution is to use events and do something like this:

class AxesResizer(object):

    def __init__(self, ax):

        self.ax = ax

        bbox = ax.get_position()

        self._orig_width = ax.figure.get_figwidth()
        self._orig_height = ax.figure.get_figheight()
        self._orig_rect = [bbox.x0, bbox.y0, bbox.width, bbox.height]

    def on_draw(self, event):

        new_width = self.ax.figure.get_figwidth()
        new_height = self.ax.figure.get_figheight()

        x0 = self._orig_rect[0] * self._orig_width / new_width
        y0 = self._orig_rect[1] * self._orig_height / new_height
        w = max(0.01, 1 - (1 - self._orig_rect[2]) * self._orig_width / new_width)
        h = max(0.01, 1 - (1 - self._orig_rect[3]) * self._orig_height / new_height)

        self.ax.set_position([x0, y0, w, h])


if __name__ == "__main__":
    fig = plt.figure()
    ax = plt.Axes(fig, [0.1, 0.1, 0.8, 0.8])
    fig.add_axes(ax)
    ax.plot([1, 2, 3])

    r = AxesResizer(ax)
    fig.canvas.mpl_connect('draw_event', r.on_draw)

    plt.show()

However, on_draw gets called after the axes are drawn, so there is a lag of one draw in the resizing of the axes, and this is noticeable (the axes 'bounce' around).

Trying resize_event instead doesn't work (it doesn't seem to work for several backends, and I see this is a common issue from a google search). Of course, if we could get that to work then that would be ideal, but given that I've found messages from people about this over several years, I'm assuming that there's a reason it hasn't been fixed.

This led me to think that in some cases such as this, once the canvas has been drawn, it's already too late, and in many cases maybe one would rather know when the canvas is about to be drawn. One could then e.g. update positions for an animation, or adjust the axes position at the last minute (like in my use case).

@mdehoon
Copy link
Contributor

mdehoon commented Sep 10, 2015

Then I think we should fix resize_event on the backends where it doesn't work.

@astrofrog
Copy link
Contributor Author

@mdehoon - I just opened an issue: #5043

If this can be fixed, I am fine with closing this issue if there is a consensus that it would not be generically useful in other cases.

@tacaswell
Copy link
Member

@astrofrog What other backends does in not work on?

@astrofrog
Copy link
Contributor Author

@tacaswell - it used not to work for me for PyQt4 either but I see that it does now. I'm happy for this issue to be closed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants