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

multiple canvas support for Windows #4236

Merged
merged 1 commit into from Mar 19, 2015
Merged

Conversation

ffteja
Copy link
Contributor

@ffteja ffteja commented Mar 17, 2015

On Windows platform the bind of the mousewheel event is made on the main application window rather than the canvas. As a side effect, if you have multiple canvas in the same application, only the last one created answers to mousewheeel events.

This patch makes the bindings chain rather than replacing each other. In the callbacks (scroll_event_windows, filter_destroy), event filtering is done to check if the canvas should answer.

@tacaswell tacaswell added this to the next point release milestone Mar 17, 2015
@tacaswell
Copy link
Member

@mdboom Who knows enough about tk to review this?

@embray
Copy link
Contributor

embray commented Mar 17, 2015

@ffteja If it's not too much trouble, could you provide some steps for reproducing the problem this fixes?

@ffteja
Copy link
Contributor Author

ffteja commented Mar 18, 2015

Here is a test script.
On windows, you won't be able to trigger the mouse wheel callback on the 1st canvas whatever the focus is. This is beacause the last canvas created has stolen the binding on the root window (see my patch)
On Linux, the mouse wheel callback called is the one of the canvase where the mouse is above. No need to prior set the focus on the canvas.

#!/usr/bin/env python

import matplotlib
matplotlib.use('TkAgg')

from numpy import arange, sin, pi
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg
from matplotlib.backend_bases import key_press_handler


from matplotlib.figure import Figure

import sys
if sys.version_info[0] < 3:
    import Tkinter as Tk
else:
    import tkinter as Tk

root = Tk.Tk()
root.wm_title("Embedding in TK")


f = Figure(figsize=(2,2), dpi=100)
a = f.add_subplot(111)
t = arange(0.0,3.0,0.01)
s = sin(2*pi*t)

a.plot(t,s)

canvas = FigureCanvasTkAgg(f, master=root)
canvas.show()
canvas.get_tk_widget().pack(side=Tk.TOP, fill=Tk.BOTH, expand=1)

def on_key_event(event):
    print("on_key_event1")

def on_wheel_event(event):
    print("on_wheel_event1")

canvas.mpl_connect('key_press_event', on_key_event)
canvas.mpl_connect('scroll_event', on_wheel_event)

canvas2 = FigureCanvasTkAgg(f, master=root)
canvas2.show()
canvas2.get_tk_widget().pack(side=Tk.TOP, fill=Tk.BOTH, expand=1)

def on_key_event2(event):
    print("on_key_event2")

def on_wheel_event2(event):
    print("on_wheel_event2")

canvas2.mpl_connect('key_press_event', on_key_event2)
canvas2.mpl_connect('scroll_event', on_wheel_event2)

def _quit():
    root.quit()     # stops mainloop
    root.destroy()  # this is necessary on Windows to prevent

button = Tk.Button(master=root, text='Focus on canvas 2', command=canvas2.get_tk_widget().focus_set)
button.pack(side=Tk.BOTTOM)

button = Tk.Button(master=root, text='Focus on canvas 1', command=canvas.get_tk_widget().focus_set)
button.pack(side=Tk.BOTTOM)

button = Tk.Button(master=root, text='Quit', command=_quit)
button.pack(side=Tk.BOTTOM)

Tk.mainloop()

[TAC edited to add markup]

@embray
Copy link
Contributor

embray commented Mar 18, 2015

@ffteja Would you mind editing your last comment to put the code sample in code blocks (see https://help.github.com/articles/github-flavored-markdown/#fenced-code-blocks)? Then the indentation can be fixed up as well.

@tacaswell
Copy link
Member

@ffteja @embray I took care of it.

@embray
Copy link
Contributor

embray commented Mar 19, 2015

I've confirmed the issue on Windows, and that this patch fixes it. Though it's totally not obvious to me why this worked on Linux when it didn't work on Windows. 🤷

@embray
Copy link
Contributor

embray commented Mar 19, 2015

Furthermore, this seems to be specifically an issue for mouse scroll events--it isn't a problem for other events. For example mouse motion events are handled by the correct canvas regardless of focus. Key events go to whichever canvas has focus, which makes sense. Same with others I tried.

@ffteja
Copy link
Contributor Author

ffteja commented Mar 19, 2015

Event launched are different in windows and linux for the mouse wheel:
linux : Button-4, Button-5
windows : MouseWheel

As you can see in the source code, the binding are different for each platform so.

@tacaswell
Copy link
Member

Is this patch harmful on linux? Do we need to platform wrap this?

@embray
Copy link
Contributor

embray commented Mar 19, 2015

No, I don't think so. It's superfluous on Linux but not at all harmful that I can tell (I tested it there too, and I don't think there's anything it would break).

tacaswell added a commit that referenced this pull request Mar 19, 2015
FIX : multiple canvas support for Windows

Correctly dispatch scroll wheel events in Tk on MS/windows
@tacaswell tacaswell merged commit d281296 into matplotlib:master Mar 19, 2015
@tacaswell
Copy link
Member

Thank you!

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

Successfully merging this pull request may close these issues.

None yet

4 participants