I have implemented a canvas with scrollable content using the mouse or trackpad. This works well if there is only one page using the mousewheel event.
The problem is that if I add a second page, the mousewheel event does not work on the first page. It will only work on the last page added.
Currently the mousewheel function is written inside each page (class). It should not have conflict of cross-referencing with the following page. It must be an issue with the event handler.
I feel that to make it right, the mousewheel function should be a class that can be accessed by the different pages, but I have no clue how to pass the event to a class and bind it with the scrollabar of each page.
I attach an example of the issue. Can anybody help please.
Thanks in advance
EDIT: Perhaps a solution could be to bind and unbind the mousewheel after leaving each page? How this would be accomplished?
import tkinter as tk
from tkinter import ttk
import numpy as np
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk
from matplotlib.figure import Figure
import matplotlib.pyplot as plt
import platform
class scrolltest (tk.Tk):
def __init__(self,*args,**kwargs):
tk.Tk.__init__(self,*args,**kwargs)
container=tk.Frame(self)
container.pack(side="top",fill="both",expand=True)
container.grid_rowconfigure(0,weight=1)
container.grid_columnconfigure(0, weight=1)
self.frames={}
for F in (StartPage,Example,Example2):
frame=F(container,self)
self.frames[F]=frame
frame.grid(row=0,column=0,sticky="nsew")
self.show_frame(StartPage)
def show_frame(self,cont):
frame=self.frames[cont]
frame.tkraise()
class StartPage(tk.Frame):
def __init__(self,parent,controller):
tk.Frame.__init__(self,parent)
button1=tk.Button(self,text="Example",command=lambda:controller.show_frame(Example))
button1.pack()
button2=tk.Button(self,text="Example2",command=lambda:controller.show_frame(Example2))
button2.pack()
class Example(tk.Frame):
def __init__(self,parent,controller):
tk.Frame.__init__(self, parent)
self.columnconfigure(0, weight=1)
self.rowconfigure(3, weight=3)
# Button
tk.Button(self,bg='red',text="Back",command=lambda:controller.show_frame(StartPage)).grid(row=0,column=0,sticky='we', padx=5, pady=10)
# Label
tk.Label(self,bg='green',text="label").grid(row=2,column=0,sticky='we',padx=5, pady=5)
# Create frame and pack
first_frame= tk.Frame(self,height=480,width=400, pady=5, padx=5)
first_frame.grid(row=3,column=0)
# Create canvas inside frame and pack
canvas=tk.Canvas(first_frame)
canvas.pack(side="left", fill="both", expand=True)
# Create a second frame inside the canvas
second_frame=tk.Canvas(canvas)
# Create canvas inside second frame
canvas.create_window((0,0), window=second_frame, anchor="nw")
# Add scrollbar to first frame
scrollbar = ttk.Scrollbar(first_frame, orient="vertical", command=canvas.yview)
# Bind scrollbar to canvas region
canvas.configure(yscrollcommand=scrollbar.set)
scrollbar.bind("<Configure>",lambda e: canvas.configure(scrollregion=canvas.bbox("all")))
# A fucntion to scroll canvas
def _on_mouse_wheel(event):
canvas.yview_scroll(-1 * int((event.delta / 120)), "units")
# Bond scroll fucntion to canvas
canvas.bind_all("<MouseWheel>", _on_mouse_wheel)
# Pack
scrollbar.pack(side="right", fill="y")
# Random data
np.random.seed(3)
x = 0.5 + np.arange(8)
y = np.random.uniform(2, 7, len(x))
# Plot 2 stacked figures
# Figure 1
fig, ax1= plt.subplots(2,figsize=(5.5,10))
ax1[0].step(x, y, linewidth=2.5)
ax1[0].set(xlim=(0, 8), xticks=np.arange(1, 8),
ylim=(0, 8), yticks=np.arange(1, 8))
ax1[1].step(x, y, linewidth=2.5)
ax1[1].set(xlim=(0, 8), xticks=np.arange(1, 8),
ylim=(0, 8), yticks=np.arange(1, 8))
# Draw into canvas and pack
canvas_fig1 = FigureCanvasTkAgg(fig,second_frame)
canvas_fig1.get_tk_widget().pack(side="bottom", fill="y")
#Figure 2
fig2, ax1= plt.subplots(2,figsize=(5.5,10))
ax1[0].step(x, y, linewidth=2.5)
ax1[0].set(xlim=(0, 8), xticks=np.arange(1, 8),
ylim=(0, 8), yticks=np.arange(1, 8))
ax1[1].step(x, y, linewidth=2.5)
ax1[1].set(xlim=(0, 8), xticks=np.arange(1, 8),
ylim=(0, 8), yticks=np.arange(1, 8))
# Draw into canvas and pack
canvas_fig2 = FigureCanvasTkAgg(fig2,second_frame)
canvas_fig2.get_tk_widget().pack(side="bottom", fill="y")
class Example2(tk.Frame):
def __init__(self,parent,controller):
tk.Frame.__init__(self, parent)
self.columnconfigure(0, weight=1)
self.rowconfigure(3, weight=3)
# Button
tk.Button(self,bg='red',text="Back",command=lambda:controller.show_frame(StartPage)).grid(row=0,column=0,sticky='we', padx=5, pady=10)
# Label
tk.Label(self,bg='green',text="label").grid(row=2,column=0,sticky='we',padx=5, pady=5)
# Create frame and pack
first_frame2= tk.Frame(self,height=480,width=400, pady=5, padx=5)
first_frame2.grid(row=3,column=0)
# Create canvas inside frame and pack
canvas2=tk.Canvas(first_frame2)
canvas2.pack(side="left", fill="both", expand=True)
# Create a second frame inside the canvas
second_frame2=tk.Canvas(canvas2)
# Create canvas inside second frame
canvas2.create_window((0,0), window=second_frame2, anchor="nw")
# Add scrollbar to first frame
scrollbar2 = ttk.Scrollbar(first_frame2, orient="vertical", command=canvas2.yview)
# Bind scrollbar to canvas region
canvas2.configure(yscrollcommand=scrollbar2.set)
scrollbar2.bind("<Configure>",lambda e: canvas2.configure(scrollregion=canvas2.bbox("all")))
# A fucntion to scroll canvas
def _on_mouse_wheel1(event):
canvas2.yview_scroll(-1 * int((event.delta / 120)), "units")
# Bond scroll fucntion to canvas
canvas2.bind_all("<MouseWheel>", _on_mouse_wheel1)
# Pack
scrollbar2.pack(side="right", fill="y")
# Random data
np.random.seed(3)
x = 0.5 + np.arange(8)
y = np.random.uniform(2, 7, len(x))
# Plot 2 stacked figures
# Figure 1
fig, ax1= plt.subplots(2,figsize=(5.5,10))
ax1[0].step(x, y, linewidth=2.5)
ax1[0].set(xlim=(0, 8), xticks=np.arange(1, 8),
ylim=(0, 8), yticks=np.arange(1, 8))
ax1[1].step(x, y, linewidth=2.5)
ax1[1].set(xlim=(0, 8), xticks=np.arange(1, 8),
ylim=(0, 8), yticks=np.arange(1, 8))
# Draw into canvas and pack
canvas_fig1 = FigureCanvasTkAgg(fig,second_frame2)
canvas_fig1.get_tk_widget().pack(side="bottom", fill="y")
#Figure 2
fig2, ax1= plt.subplots(2,figsize=(5.5,10))
ax1[0].step(x, y, linewidth=2.5)
ax1[0].set(xlim=(0, 8), xticks=np.arange(1, 8),
ylim=(0, 8), yticks=np.arange(1, 8))
ax1[1].step(x, y, linewidth=2.5)
ax1[1].set(xlim=(0, 8), xticks=np.arange(1, 8),
ylim=(0, 8), yticks=np.arange(1, 8))
# Draw into canvas and pack
canvas_fig2 = FigureCanvasTkAgg(fig2,second_frame2)
canvas_fig2.get_tk_widget().pack(side="bottom", fill="y")
app=scrolltest()
app.title("Scrollfigure")
app.mainloop()