英文:
How to bind scrollbar of left canvas and right canvas to wheel events correctly?
问题
I have two scrollbars, i.e. on the left and right frame. I have created two mouse events to bind scroll wheel with each scrollbar. If I am on the left frame and I scroll with the scroll wheel, I would expect that the left frame's scrollbar would scroll, too. But, in my implementation, only the right frame's scrollbar moves. I could not figure out the problem in my script. I appreciate any help.
英文:
I have two scrollbars, i.e. on the left and right frame. I have created two mouse events to bind scroll wheel with each scrollbar. If I am on left frame and I scroll with scroll wheel, I would expect that scrollbar of left frame would scroll, too. But, in my implementation, only scrollbar of right frame moves. I could not figure out the problem in my script. I appreciate any help.
import tkinter as tk
from tkinter import ttk
import pandas as pd
import random
# Sample DataFrame
df = pd.DataFrame({
'ID': [1, 2, 3, 4, 5],
'Data': [10, 15, 7, 12, 9]
})
def create_radial_chart(frame):
# Function to create a random radial chart
# Replace this with your own radial chart creation code
# For demonstration purposes, we'll just create a random number of labels
num_labels = random.randint(1, 80)
labels = [f'Label {i}' for i in range(1, num_labels + 1)]
radial_chart = ttk.Label(frame, text='\n'.join(labels))
radial_chart.pack()
def on_left_canvas_scroll(event):
left_canvas.yview_scroll(int(-1 * (event.delta / 120)), "units")
update_left_scrollbar()
def update_left_scrollbar():
left_scrollbar.set(*left_canvas.yview())
# Create the main window
root = tk.Tk()
root.title('Tkinter Layout Example')
# Create the dropdown menu
dropdown_var = tk.StringVar(root)
dropdown = ttk.Combobox(root, textvariable=dropdown_var)
dropdown['values'] = df['ID'].unique()
dropdown.pack()
# Create the main frames
main_frame = ttk.Frame(root)
main_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
# Create the left frame with a scrollbar
left_frame = ttk.Frame(main_frame)
left_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
left_scrollbar = ttk.Scrollbar(left_frame, orient=tk.VERTICAL)
left_scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
left_canvas = tk.Canvas(left_frame, yscrollcommand=left_scrollbar.set)
left_canvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
left_scrollbar.config(command=left_canvas.yview)
# Bind scroll wheel event to the left frame content
left_frame_content = ttk.Frame(left_canvas)
left_canvas.create_window((0, 0), window=left_frame_content, anchor='nw')
left_frame_content.bind_all("<MouseWheel>", on_left_canvas_scroll)
# Create the radial charts in the left frame
for _ in range(5):
create_radial_chart(left_frame_content)
# Configure the scrollable region for the left canvas
left_frame_content.update_idletasks()
left_canvas.config(scrollregion=left_canvas.bbox("all"))
# Update the left scrollbar initially
update_left_scrollbar()
# Create the right frame with a scrollbar
right_frame = ttk.Frame(main_frame)
right_frame.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True)
right_scrollbar = ttk.Scrollbar(right_frame, orient=tk.VERTICAL)
right_scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
right_canvas = tk.Canvas(right_frame, yscrollcommand=right_scrollbar.set)
right_canvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
right_scrollbar.config(command=right_canvas.yview)
# Bind scroll wheel event to the right canvas
right_canvas.bind_all("<MouseWheel>", lambda event: right_canvas.yview_scroll(int(-1 * (event.delta / 120)), "units"))
# Create the middle frames
middle_frame = ttk.Frame(main_frame)
middle_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, padx=10)
upper_middle_frame = ttk.Frame(middle_frame)
upper_middle_frame.pack(fill=tk.BOTH, expand=True)
lower_middle_frame = ttk.Frame(middle_frame)
lower_middle_frame.pack(fill=tk.BOTH, expand=True)
# Create the line plot in the upper middle frame
# Replace this with your own line plot creation code
line_plot = ttk.Label(upper_middle_frame, text='Line Plot')
line_plot.pack()
# Create the data table in the lower middle frame
# Replace this with your own data table creation code
data_table = ttk.Label(lower_middle_frame, text='Data Table')
data_table.pack()
# Create the radial charts in the right frame
right_frame_content = ttk.Frame(right_canvas)
right_canvas.create_window((0, 0), window=right_frame_content, anchor='nw')
for _ in range(5):
create_radial_chart(right_frame_content)
# Configure the scrollable region for the right canvas
right_frame_content.update_idletasks()
right_canvas.config(scrollregion=right_canvas.bbox("all"))
root.mainloop()
答案1
得分: 1
这是因为 right_canvas.bind_all(...)
会覆盖 left_canvas.bind_all(...)
。你需要检查哪个部件触发了事件,然后确定滚动相应的画布:
def mouse_scroll(event):
# 检查是左侧画布还是左侧画布内的标签触发了事件?
left = (event.widget is left_canvas) or \
(event.widget.master and event.widget.master is left_frame_content)
# 检查是右侧画布还是右侧画布内的标签触发了事件?
right = (event.widget is right_canvas) or \
(event.widget.master and event.widget.master is right_frame_content)
if left:
left_canvas.yview_scroll(int(-1 * (event.delta / 120)), "units")
elif right:
right_canvas.yview_scroll(int(-1 * (event.delta / 120)), "units")
# 只需调用一次 `bind_all()`
root.bind_all("<MouseWheel>", mouse_scroll)
英文:
It is because right_canvas.bind_all(...)
will override left_canvas.bind_all(...)
. You need to check which widget triggers the event and determine to scroll the corresponding canvas:
def mouse_scroll(event):
# Does left canvas or labels inside left canvas trigger the event?
left = (event.widget is left_canvas) or \
(event.widget.master and event.widget.master is left_frame_content)
# Does right canvas or labels inside right canvas trigger the event?
right = (event.widget is right_canvas) or \
(event.widget.master and event.widget.master is right_frame_content)
if left:
left_canvas.yview_scroll(int(-1 * (event.delta / 120)), "units")
elif right:
right_canvas.yview_scroll(int(-1 * (event.delta / 120)), "units")
# just call `bind_all()` once
root.bind_all("<MouseWheel>", mouse_scroll)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论